diff options
Diffstat (limited to 'drivers/nvmem/lpc18xx_eeprom.c')
| -rw-r--r-- | drivers/nvmem/lpc18xx_eeprom.c | 94 |
1 files changed, 26 insertions, 68 deletions
diff --git a/drivers/nvmem/lpc18xx_eeprom.c b/drivers/nvmem/lpc18xx_eeprom.c index 878fce789341..c81ae4c6da74 100644 --- a/drivers/nvmem/lpc18xx_eeprom.c +++ b/drivers/nvmem/lpc18xx_eeprom.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/nvmem-provider.h> | 17 | #include <linux/nvmem-provider.h> |
| 18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
| 19 | #include <linux/regmap.h> | ||
| 20 | #include <linux/reset.h> | 19 | #include <linux/reset.h> |
| 21 | 20 | ||
| 22 | /* Registers */ | 21 | /* Registers */ |
| @@ -51,12 +50,7 @@ struct lpc18xx_eeprom_dev { | |||
| 51 | struct nvmem_device *nvmem; | 50 | struct nvmem_device *nvmem; |
| 52 | unsigned reg_bytes; | 51 | unsigned reg_bytes; |
| 53 | unsigned val_bytes; | 52 | unsigned val_bytes; |
| 54 | }; | 53 | int size; |
| 55 | |||
| 56 | static struct regmap_config lpc18xx_regmap_config = { | ||
| 57 | .reg_bits = 32, | ||
| 58 | .reg_stride = 4, | ||
| 59 | .val_bits = 32, | ||
| 60 | }; | 54 | }; |
| 61 | 55 | ||
| 62 | static inline void lpc18xx_eeprom_writel(struct lpc18xx_eeprom_dev *eeprom, | 56 | static inline void lpc18xx_eeprom_writel(struct lpc18xx_eeprom_dev *eeprom, |
| @@ -95,30 +89,35 @@ static int lpc18xx_eeprom_busywait_until_prog(struct lpc18xx_eeprom_dev *eeprom) | |||
| 95 | return -ETIMEDOUT; | 89 | return -ETIMEDOUT; |
| 96 | } | 90 | } |
| 97 | 91 | ||
| 98 | static int lpc18xx_eeprom_gather_write(void *context, const void *reg, | 92 | static int lpc18xx_eeprom_gather_write(void *context, unsigned int reg, |
| 99 | size_t reg_size, const void *val, | 93 | void *val, size_t bytes) |
| 100 | size_t val_size) | ||
| 101 | { | 94 | { |
| 102 | struct lpc18xx_eeprom_dev *eeprom = context; | 95 | struct lpc18xx_eeprom_dev *eeprom = context; |
| 103 | unsigned int offset = *(u32 *)reg; | 96 | unsigned int offset = reg; |
| 104 | int ret; | 97 | int ret; |
| 105 | 98 | ||
| 106 | if (offset % lpc18xx_regmap_config.reg_stride) | 99 | /* |
| 100 | * The last page contains the EEPROM initialization data and is not | ||
| 101 | * writable. | ||
| 102 | */ | ||
| 103 | if ((reg > eeprom->size - LPC18XX_EEPROM_PAGE_SIZE) || | ||
| 104 | (reg + bytes > eeprom->size - LPC18XX_EEPROM_PAGE_SIZE)) | ||
| 107 | return -EINVAL; | 105 | return -EINVAL; |
| 108 | 106 | ||
| 107 | |||
| 109 | lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN, | 108 | lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN, |
| 110 | LPC18XX_EEPROM_PWRDWN_NO); | 109 | LPC18XX_EEPROM_PWRDWN_NO); |
| 111 | 110 | ||
| 112 | /* Wait 100 us while the EEPROM wakes up */ | 111 | /* Wait 100 us while the EEPROM wakes up */ |
| 113 | usleep_range(100, 200); | 112 | usleep_range(100, 200); |
| 114 | 113 | ||
| 115 | while (val_size) { | 114 | while (bytes) { |
| 116 | writel(*(u32 *)val, eeprom->mem_base + offset); | 115 | writel(*(u32 *)val, eeprom->mem_base + offset); |
| 117 | ret = lpc18xx_eeprom_busywait_until_prog(eeprom); | 116 | ret = lpc18xx_eeprom_busywait_until_prog(eeprom); |
| 118 | if (ret < 0) | 117 | if (ret < 0) |
| 119 | return ret; | 118 | return ret; |
| 120 | 119 | ||
| 121 | val_size -= eeprom->val_bytes; | 120 | bytes -= eeprom->val_bytes; |
| 122 | val += eeprom->val_bytes; | 121 | val += eeprom->val_bytes; |
| 123 | offset += eeprom->val_bytes; | 122 | offset += eeprom->val_bytes; |
| 124 | } | 123 | } |
| @@ -129,23 +128,10 @@ static int lpc18xx_eeprom_gather_write(void *context, const void *reg, | |||
| 129 | return 0; | 128 | return 0; |
| 130 | } | 129 | } |
| 131 | 130 | ||
| 132 | static int lpc18xx_eeprom_write(void *context, const void *data, size_t count) | 131 | static int lpc18xx_eeprom_read(void *context, unsigned int offset, |
| 132 | void *val, size_t bytes) | ||
| 133 | { | 133 | { |
| 134 | struct lpc18xx_eeprom_dev *eeprom = context; | 134 | struct lpc18xx_eeprom_dev *eeprom = context; |
| 135 | unsigned int offset = eeprom->reg_bytes; | ||
| 136 | |||
| 137 | if (count <= offset) | ||
| 138 | return -EINVAL; | ||
| 139 | |||
| 140 | return lpc18xx_eeprom_gather_write(context, data, eeprom->reg_bytes, | ||
| 141 | data + offset, count - offset); | ||
| 142 | } | ||
| 143 | |||
| 144 | static int lpc18xx_eeprom_read(void *context, const void *reg, size_t reg_size, | ||
| 145 | void *val, size_t val_size) | ||
| 146 | { | ||
| 147 | struct lpc18xx_eeprom_dev *eeprom = context; | ||
| 148 | unsigned int offset = *(u32 *)reg; | ||
| 149 | 135 | ||
| 150 | lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN, | 136 | lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN, |
| 151 | LPC18XX_EEPROM_PWRDWN_NO); | 137 | LPC18XX_EEPROM_PWRDWN_NO); |
| @@ -153,9 +139,9 @@ static int lpc18xx_eeprom_read(void *context, const void *reg, size_t reg_size, | |||
| 153 | /* Wait 100 us while the EEPROM wakes up */ | 139 | /* Wait 100 us while the EEPROM wakes up */ |
| 154 | usleep_range(100, 200); | 140 | usleep_range(100, 200); |
| 155 | 141 | ||
| 156 | while (val_size) { | 142 | while (bytes) { |
| 157 | *(u32 *)val = readl(eeprom->mem_base + offset); | 143 | *(u32 *)val = readl(eeprom->mem_base + offset); |
| 158 | val_size -= eeprom->val_bytes; | 144 | bytes -= eeprom->val_bytes; |
| 159 | val += eeprom->val_bytes; | 145 | val += eeprom->val_bytes; |
| 160 | offset += eeprom->val_bytes; | 146 | offset += eeprom->val_bytes; |
| 161 | } | 147 | } |
| @@ -166,31 +152,13 @@ static int lpc18xx_eeprom_read(void *context, const void *reg, size_t reg_size, | |||
| 166 | return 0; | 152 | return 0; |
| 167 | } | 153 | } |
| 168 | 154 | ||
| 169 | static struct regmap_bus lpc18xx_eeprom_bus = { | ||
| 170 | .write = lpc18xx_eeprom_write, | ||
| 171 | .gather_write = lpc18xx_eeprom_gather_write, | ||
| 172 | .read = lpc18xx_eeprom_read, | ||
| 173 | .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
| 174 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
| 175 | }; | ||
| 176 | |||
| 177 | static bool lpc18xx_eeprom_writeable_reg(struct device *dev, unsigned int reg) | ||
| 178 | { | ||
| 179 | /* | ||
| 180 | * The last page contains the EEPROM initialization data and is not | ||
| 181 | * writable. | ||
| 182 | */ | ||
| 183 | return reg <= lpc18xx_regmap_config.max_register - | ||
| 184 | LPC18XX_EEPROM_PAGE_SIZE; | ||
| 185 | } | ||
| 186 | |||
| 187 | static bool lpc18xx_eeprom_readable_reg(struct device *dev, unsigned int reg) | ||
| 188 | { | ||
| 189 | return reg <= lpc18xx_regmap_config.max_register; | ||
| 190 | } | ||
| 191 | 155 | ||
| 192 | static struct nvmem_config lpc18xx_nvmem_config = { | 156 | static struct nvmem_config lpc18xx_nvmem_config = { |
| 193 | .name = "lpc18xx-eeprom", | 157 | .name = "lpc18xx-eeprom", |
| 158 | .stride = 4, | ||
| 159 | .word_size = 4, | ||
| 160 | .reg_read = lpc18xx_eeprom_read, | ||
| 161 | .reg_write = lpc18xx_eeprom_gather_write, | ||
| 194 | .owner = THIS_MODULE, | 162 | .owner = THIS_MODULE, |
| 195 | }; | 163 | }; |
| 196 | 164 | ||
| @@ -200,7 +168,6 @@ static int lpc18xx_eeprom_probe(struct platform_device *pdev) | |||
| 200 | struct device *dev = &pdev->dev; | 168 | struct device *dev = &pdev->dev; |
| 201 | struct reset_control *rst; | 169 | struct reset_control *rst; |
| 202 | unsigned long clk_rate; | 170 | unsigned long clk_rate; |
| 203 | struct regmap *regmap; | ||
| 204 | struct resource *res; | 171 | struct resource *res; |
| 205 | int ret; | 172 | int ret; |
| 206 | 173 | ||
| @@ -243,8 +210,8 @@ static int lpc18xx_eeprom_probe(struct platform_device *pdev) | |||
| 243 | goto err_clk; | 210 | goto err_clk; |
| 244 | } | 211 | } |
| 245 | 212 | ||
| 246 | eeprom->val_bytes = lpc18xx_regmap_config.val_bits / BITS_PER_BYTE; | 213 | eeprom->val_bytes = 4; |
| 247 | eeprom->reg_bytes = lpc18xx_regmap_config.reg_bits / BITS_PER_BYTE; | 214 | eeprom->reg_bytes = 4; |
| 248 | 215 | ||
| 249 | /* | 216 | /* |
| 250 | * Clock rate is generated by dividing the system bus clock by the | 217 | * Clock rate is generated by dividing the system bus clock by the |
| @@ -264,19 +231,10 @@ static int lpc18xx_eeprom_probe(struct platform_device *pdev) | |||
| 264 | lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN, | 231 | lpc18xx_eeprom_writel(eeprom, LPC18XX_EEPROM_PWRDWN, |
| 265 | LPC18XX_EEPROM_PWRDWN_YES); | 232 | LPC18XX_EEPROM_PWRDWN_YES); |
| 266 | 233 | ||
| 267 | lpc18xx_regmap_config.max_register = resource_size(res) - 1; | 234 | eeprom->size = resource_size(res); |
| 268 | lpc18xx_regmap_config.writeable_reg = lpc18xx_eeprom_writeable_reg; | 235 | lpc18xx_nvmem_config.size = resource_size(res); |
| 269 | lpc18xx_regmap_config.readable_reg = lpc18xx_eeprom_readable_reg; | ||
| 270 | |||
| 271 | regmap = devm_regmap_init(dev, &lpc18xx_eeprom_bus, eeprom, | ||
| 272 | &lpc18xx_regmap_config); | ||
| 273 | if (IS_ERR(regmap)) { | ||
| 274 | dev_err(dev, "regmap init failed: %ld\n", PTR_ERR(regmap)); | ||
| 275 | ret = PTR_ERR(regmap); | ||
| 276 | goto err_clk; | ||
| 277 | } | ||
| 278 | |||
| 279 | lpc18xx_nvmem_config.dev = dev; | 236 | lpc18xx_nvmem_config.dev = dev; |
| 237 | lpc18xx_nvmem_config.priv = eeprom; | ||
| 280 | 238 | ||
| 281 | eeprom->nvmem = nvmem_register(&lpc18xx_nvmem_config); | 239 | eeprom->nvmem = nvmem_register(&lpc18xx_nvmem_config); |
| 282 | if (IS_ERR(eeprom->nvmem)) { | 240 | if (IS_ERR(eeprom->nvmem)) { |
