1 /* 2 * Base driver for Marvell 88PM8607 3 * 4 * Copyright (C) 2009 Marvell International Ltd. 5 * Haojian Zhuang <haojian.zhuang@marvell.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/interrupt.h> 15 #include <linux/platform_device.h> 16 #include <linux/mfd/core.h> 17 #include <linux/mfd/88pm860x.h> 18 19 20 #define PM8607_REG_RESOURCE(_start, _end) \ 21 { \ 22 .start = PM8607_##_start, \ 23 .end = PM8607_##_end, \ 24 .flags = IORESOURCE_IO, \ 25 } 26 27 static struct resource pm8607_regulator_resources[] = { 28 PM8607_REG_RESOURCE(BUCK1, BUCK1), 29 PM8607_REG_RESOURCE(BUCK2, BUCK2), 30 PM8607_REG_RESOURCE(BUCK3, BUCK3), 31 PM8607_REG_RESOURCE(LDO1, LDO1), 32 PM8607_REG_RESOURCE(LDO2, LDO2), 33 PM8607_REG_RESOURCE(LDO3, LDO3), 34 PM8607_REG_RESOURCE(LDO4, LDO4), 35 PM8607_REG_RESOURCE(LDO5, LDO5), 36 PM8607_REG_RESOURCE(LDO6, LDO6), 37 PM8607_REG_RESOURCE(LDO7, LDO7), 38 PM8607_REG_RESOURCE(LDO8, LDO8), 39 PM8607_REG_RESOURCE(LDO9, LDO9), 40 PM8607_REG_RESOURCE(LDO10, LDO10), 41 PM8607_REG_RESOURCE(LDO12, LDO12), 42 PM8607_REG_RESOURCE(LDO14, LDO14), 43 }; 44 45 #define PM8607_REG_DEVS(_name, _id) \ 46 { \ 47 .name = "88pm8607-" #_name, \ 48 .num_resources = 1, \ 49 .resources = &pm8607_regulator_resources[PM8607_ID_##_id], \ 50 } 51 52 static struct mfd_cell pm8607_devs[] = { 53 PM8607_REG_DEVS(buck1, BUCK1), 54 PM8607_REG_DEVS(buck2, BUCK2), 55 PM8607_REG_DEVS(buck3, BUCK3), 56 PM8607_REG_DEVS(ldo1, LDO1), 57 PM8607_REG_DEVS(ldo2, LDO2), 58 PM8607_REG_DEVS(ldo3, LDO3), 59 PM8607_REG_DEVS(ldo4, LDO4), 60 PM8607_REG_DEVS(ldo5, LDO5), 61 PM8607_REG_DEVS(ldo6, LDO6), 62 PM8607_REG_DEVS(ldo7, LDO7), 63 PM8607_REG_DEVS(ldo8, LDO8), 64 PM8607_REG_DEVS(ldo9, LDO9), 65 PM8607_REG_DEVS(ldo10, LDO10), 66 PM8607_REG_DEVS(ldo12, LDO12), 67 PM8607_REG_DEVS(ldo14, LDO14), 68 }; 69 70 static void device_8606_init(struct pm860x_chip *chip, struct i2c_client *i2c, 71 struct pm860x_platform_data *pdata) 72 { 73 } 74 75 static void device_8607_init(struct pm860x_chip *chip, struct i2c_client *i2c, 76 struct pm860x_platform_data *pdata) 77 { 78 int i, count; 79 int ret; 80 81 ret = pm860x_reg_read(i2c, PM8607_CHIP_ID); 82 if (ret < 0) { 83 dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); 84 goto out; 85 } 86 if ((ret & PM8607_VERSION_MASK) == PM8607_VERSION) 87 dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", 88 ret); 89 else { 90 dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " 91 "Chip ID: %02x\n", ret); 92 goto out; 93 } 94 chip->chip_version = ret; 95 96 ret = pm860x_reg_read(i2c, PM8607_BUCK3); 97 if (ret < 0) { 98 dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret); 99 goto out; 100 } 101 if (ret & PM8607_BUCK3_DOUBLE) 102 chip->buck3_double = 1; 103 104 ret = pm860x_reg_read(i2c, PM8607_MISC1); 105 if (ret < 0) { 106 dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret); 107 goto out; 108 } 109 110 count = ARRAY_SIZE(pm8607_devs); 111 for (i = 0; i < count; i++) { 112 ret = mfd_add_devices(chip->dev, i, &pm8607_devs[i], 113 1, NULL, 0); 114 if (ret != 0) { 115 dev_err(chip->dev, "Failed to add subdevs\n"); 116 goto out; 117 } 118 } 119 out: 120 return; 121 } 122 123 int pm860x_device_init(struct pm860x_chip *chip, 124 struct pm860x_platform_data *pdata) 125 { 126 switch (chip->id) { 127 case CHIP_PM8606: 128 device_8606_init(chip, chip->client, pdata); 129 break; 130 case CHIP_PM8607: 131 device_8607_init(chip, chip->client, pdata); 132 break; 133 } 134 135 if (chip->companion) { 136 switch (chip->id) { 137 case CHIP_PM8607: 138 device_8606_init(chip, chip->companion, pdata); 139 break; 140 case CHIP_PM8606: 141 device_8607_init(chip, chip->companion, pdata); 142 break; 143 } 144 } 145 return 0; 146 } 147 148 void pm860x_device_exit(struct pm860x_chip *chip) 149 { 150 mfd_remove_devices(chip->dev); 151 } 152 153 MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x"); 154 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 155 MODULE_LICENSE("GPL"); 156