diff options
Diffstat (limited to 'drivers/mfd/sm501.c')
| -rw-r--r-- | drivers/mfd/sm501.c | 196 |
1 files changed, 72 insertions, 124 deletions
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 40534352e574..50bf3260f65d 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* linux/drivers/mfd/sm501.c * * Copyright (C) 2006 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * Vincent Sanders <vince@simtec.co.uk> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * * SM501 MFD driver */ @@ -19,7 +16,9 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/pci.h> -#include <linux/i2c-gpio.h> +#include <linux/platform_data/i2c-gpio.h> +#include <linux/gpio/driver.h> +#include <linux/gpio/machine.h> #include <linux/slab.h> #include <linux/sm501.h> @@ -632,49 +631,6 @@ unsigned long sm501_set_clock(struct device *dev, EXPORT_SYMBOL_GPL(sm501_set_clock); -/* sm501_find_clock - * - * finds the closest available frequency for a given clock -*/ - -unsigned long sm501_find_clock(struct device *dev, - int clksrc, - unsigned long req_freq) -{ - struct sm501_devdata *sm = dev_get_drvdata(dev); - unsigned long sm501_freq; /* the frequency achieveable by the 501 */ - struct sm501_clock to; - - switch (clksrc) { - case SM501_CLOCK_P2XCLK: - if (sm->rev >= 0xC0) { - /* SM502 -> use the programmable PLL */ - sm501_freq = (sm501_calc_pll(2 * req_freq, - &to, 5) / 2); - } else { - sm501_freq = (sm501_select_clock(2 * req_freq, - &to, 5) / 2); - } - break; - - case SM501_CLOCK_V2XCLK: - sm501_freq = (sm501_select_clock(2 * req_freq, &to, 3) / 2); - break; - - case SM501_CLOCK_MCLK: - case SM501_CLOCK_M1XCLK: - sm501_freq = sm501_select_clock(req_freq, &to, 3); - break; - - default: - sm501_freq = 0; /* error */ - } - - return sm501_freq; -} - -EXPORT_SYMBOL_GPL(sm501_find_clock); - static struct sm501_device *to_sm_device(struct platform_device *pdev) { return container_of(pdev, struct sm501_device, pdev); @@ -714,6 +670,7 @@ sm501_create_subdev(struct sm501_devdata *sm, char *name, smdev->pdev.name = name; smdev->pdev.id = sm->pdev_id; smdev->pdev.dev.parent = sm->dev; + smdev->pdev.dev.coherent_dma_mask = 0xffffffff; if (res_count) { smdev->pdev.resource = (struct resource *)(smdev+1); @@ -915,12 +872,13 @@ static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip, } } -static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static int sm501_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); struct sm501_gpio *smgpio = smchip->ourgpio; - unsigned long bit = 1 << offset; + unsigned long bit = BIT(offset); void __iomem *regs = smchip->regbase; unsigned long save; unsigned long val; @@ -939,6 +897,8 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value) sm501_gpio_ensure_gpio(smchip, bit); spin_unlock_irqrestore(&smgpio->lock, save); + + return 0; } static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset) @@ -946,7 +906,7 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset) struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); struct sm501_gpio *smgpio = smchip->ourgpio; void __iomem *regs = smchip->regbase; - unsigned long bit = 1 << offset; + unsigned long bit = BIT(offset); unsigned long save; unsigned long ddr; @@ -971,7 +931,7 @@ static int sm501_gpio_output(struct gpio_chip *chip, { struct sm501_gpio_chip *smchip = gpiochip_get_data(chip); struct sm501_gpio *smgpio = smchip->ourgpio; - unsigned long bit = 1 << offset; + unsigned long bit = BIT(offset); void __iomem *regs = smchip->regbase; unsigned long save; unsigned long val; @@ -1049,13 +1009,13 @@ static int sm501_register_gpio(struct sm501_devdata *sm) spin_lock_init(&gpio->lock); gpio->regs_res = request_mem_region(iobase, 0x20, "sm501-gpio"); - if (gpio->regs_res == NULL) { + if (!gpio->regs_res) { dev_err(sm->dev, "gpio: failed to request region\n"); return -ENXIO; } gpio->regs = ioremap(iobase, 0x20); - if (gpio->regs == NULL) { + if (!gpio->regs) { dev_err(sm->dev, "gpio: failed to remap registers\n"); ret = -ENXIO; goto err_claimed; @@ -1086,8 +1046,7 @@ static int sm501_register_gpio(struct sm501_devdata *sm) iounmap(gpio->regs); err_claimed: - release_resource(gpio->regs_res); - kfree(gpio->regs_res); + release_mem_region(iobase, 0x20); return ret; } @@ -1095,6 +1054,7 @@ static int sm501_register_gpio(struct sm501_devdata *sm) static void sm501_gpio_remove(struct sm501_devdata *sm) { struct sm501_gpio *gpio = &sm->gpio; + resource_size_t iobase = sm->io_res->start + SM501_GPIO; if (!sm->gpio.registered) return; @@ -1103,16 +1063,7 @@ static void sm501_gpio_remove(struct sm501_devdata *sm) gpiochip_remove(&gpio->high.gpio); iounmap(gpio->regs); - release_resource(gpio->regs_res); - kfree(gpio->regs_res); -} - -static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin) -{ - struct sm501_gpio *gpio = &sm->gpio; - int base = (pin < 32) ? gpio->low.gpio.base : gpio->high.gpio.base; - - return (pin % 32) + base; + release_mem_region(iobase, 0x20); } static inline int sm501_gpio_isregistered(struct sm501_devdata *sm) @@ -1129,11 +1080,6 @@ static inline void sm501_gpio_remove(struct sm501_devdata *sm) { } -static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin) -{ - return -1; -} - static inline int sm501_gpio_isregistered(struct sm501_devdata *sm) { return 0; @@ -1145,20 +1091,31 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm, { struct i2c_gpio_platform_data *icd; struct platform_device *pdev; + struct gpiod_lookup_table *lookup; pdev = sm501_create_subdev(sm, "i2c-gpio", 0, sizeof(struct i2c_gpio_platform_data)); if (!pdev) return -ENOMEM; - icd = dev_get_platdata(&pdev->dev); + /* Create a gpiod lookup using gpiochip-local offsets */ + lookup = devm_kzalloc(&pdev->dev, struct_size(lookup, table, 3), + GFP_KERNEL); + if (!lookup) + return -ENOMEM; - /* We keep the pin_sda and pin_scl fields relative in case the - * same platform data is passed to >1 SM501. - */ + lookup->dev_id = "i2c-gpio"; + lookup->table[0] = (struct gpiod_lookup) + GPIO_LOOKUP_IDX(iic->pin_sda < 32 ? "SM501-LOW" : "SM501-HIGH", + iic->pin_sda % 32, NULL, 0, + GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN); + lookup->table[1] = (struct gpiod_lookup) + GPIO_LOOKUP_IDX(iic->pin_scl < 32 ? "SM501-LOW" : "SM501-HIGH", + iic->pin_scl % 32, NULL, 1, + GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN); + gpiod_add_lookup_table(lookup); - icd->sda_pin = sm501_gpio_pin2nr(sm, iic->pin_sda); - icd->scl_pin = sm501_gpio_pin2nr(sm, iic->pin_scl); + icd = dev_get_platdata(&pdev->dev); icd->timeout = iic->timeout; icd->udelay = iic->udelay; @@ -1170,9 +1127,9 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm, pdev->id = iic->bus_num; - dev_info(sm->dev, "registering i2c-%d: sda=%d (%d), scl=%d (%d)\n", + dev_info(sm->dev, "registering i2c-%d: sda=%d, scl=%d\n", iic->bus_num, - icd->sda_pin, iic->pin_sda, icd->scl_pin, iic->pin_scl); + iic->pin_sda, iic->pin_scl); return sm501_register_device(sm, pdev); } @@ -1193,13 +1150,13 @@ static int sm501_register_gpio_i2c(struct sm501_devdata *sm, return 0; } -/* sm501_dbg_regs +/* dbg_regs_show * * Debug attribute to attach to parent device to show core registers */ -static ssize_t sm501_dbg_regs(struct device *dev, - struct device_attribute *attr, char *buff) +static ssize_t dbg_regs_show(struct device *dev, + struct device_attribute *attr, char *buff) { struct sm501_devdata *sm = dev_get_drvdata(dev) ; unsigned int reg; @@ -1216,7 +1173,7 @@ static ssize_t sm501_dbg_regs(struct device *dev, } -static DEVICE_ATTR(dbg_regs, 0444, sm501_dbg_regs, NULL); +static DEVICE_ATTR_RO(dbg_regs); /* sm501_init_reg * @@ -1353,7 +1310,7 @@ static int sm501_init_dev(struct sm501_devdata *sm) sm501_register_gpio(sm); } - if (pdata && pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) { + if (pdata && pdata->gpio_i2c && pdata->gpio_i2c_nr > 0) { if (!sm501_gpio_isregistered(sm)) dev_err(sm->dev, "no gpio available for i2c gpio.\n"); else @@ -1378,9 +1335,8 @@ static int sm501_plat_probe(struct platform_device *dev) struct sm501_devdata *sm; int ret; - sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL); - if (sm == NULL) { - dev_err(&dev->dev, "no memory for device data\n"); + sm = kzalloc(sizeof(*sm), GFP_KERNEL); + if (!sm) { ret = -ENOMEM; goto err1; } @@ -1390,16 +1346,13 @@ static int sm501_plat_probe(struct platform_device *dev) sm->platdata = dev_get_platdata(&dev->dev); ret = platform_get_irq(dev, 0); - if (ret < 0) { - dev_err(&dev->dev, "failed to get irq resource\n"); + if (ret < 0) goto err_res; - } sm->irq = ret; sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1); sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0); - - if (sm->io_res == NULL || sm->mem_res == NULL) { + if (!sm->io_res || !sm->mem_res) { dev_err(&dev->dev, "failed to get IO resource\n"); ret = -ENOENT; goto err_res; @@ -1407,8 +1360,7 @@ static int sm501_plat_probe(struct platform_device *dev) sm->regs_claim = request_mem_region(sm->io_res->start, 0x100, "sm501"); - - if (sm->regs_claim == NULL) { + if (!sm->regs_claim) { dev_err(&dev->dev, "cannot claim registers\n"); ret = -EBUSY; goto err_res; @@ -1417,18 +1369,22 @@ static int sm501_plat_probe(struct platform_device *dev) platform_set_drvdata(dev, sm); sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res)); - - if (sm->regs == NULL) { + if (!sm->regs) { dev_err(&dev->dev, "cannot remap registers\n"); ret = -EIO; goto err_claim; } - return sm501_init_dev(sm); + ret = sm501_init_dev(sm); + if (ret) + goto err_unmap; + + return 0; + err_unmap: + iounmap(sm->regs); err_claim: - release_resource(sm->regs_claim); - kfree(sm->regs_claim); + release_mem_region(sm->io_res->start, 0x100); err_res: kfree(sm); err1: @@ -1436,15 +1392,13 @@ static int sm501_plat_probe(struct platform_device *dev) } -#ifdef CONFIG_PM - /* power management support */ static void sm501_set_power(struct sm501_devdata *sm, int on) { struct sm501_platdata *pd = sm->platdata; - if (pd == NULL) + if (!pd) return; if (pd->get_power) { @@ -1513,10 +1467,6 @@ static int sm501_plat_resume(struct platform_device *pdev) return 0; } -#else -#define sm501_plat_suspend NULL -#define sm501_plat_resume NULL -#endif /* Initialisation data for PCI devices */ @@ -1568,9 +1518,8 @@ static int sm501_pci_probe(struct pci_dev *dev, struct sm501_devdata *sm; int err; - sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL); - if (sm == NULL) { - dev_err(&dev->dev, "no memory for device data\n"); + sm = kzalloc(sizeof(*sm), GFP_KERNEL); + if (!sm) { err = -ENOMEM; goto err1; } @@ -1621,15 +1570,14 @@ static int sm501_pci_probe(struct pci_dev *dev, sm->regs_claim = request_mem_region(sm->io_res->start, 0x100, "sm501"); - if (sm->regs_claim == NULL) { + if (!sm->regs_claim) { dev_err(&dev->dev, "cannot claim registers\n"); err= -EBUSY; goto err3; } sm->regs = pci_ioremap_bar(dev, 1); - - if (sm->regs == NULL) { + if (!sm->regs) { dev_err(&dev->dev, "cannot remap registers\n"); err = -EIO; goto err4; @@ -1639,8 +1587,7 @@ static int sm501_pci_probe(struct pci_dev *dev, return 0; err4: - release_resource(sm->regs_claim); - kfree(sm->regs_claim); + release_mem_region(sm->io_res->start, 0x100); err3: pci_disable_device(dev); err2: @@ -1675,23 +1622,19 @@ static void sm501_pci_remove(struct pci_dev *dev) sm501_dev_remove(sm); iounmap(sm->regs); - release_resource(sm->regs_claim); - kfree(sm->regs_claim); + release_mem_region(sm->io_res->start, 0x100); pci_disable_device(dev); } -static int sm501_plat_remove(struct platform_device *dev) +static void sm501_plat_remove(struct platform_device *dev) { struct sm501_devdata *sm = platform_get_drvdata(dev); sm501_dev_remove(sm); iounmap(sm->regs); - release_resource(sm->regs_claim); - kfree(sm->regs_claim); - - return 0; + release_mem_region(sm->io_res->start, 0x100); } static const struct pci_device_id sm501_pci_tbl[] = { @@ -1723,13 +1666,18 @@ static struct platform_driver sm501_plat_driver = { }, .probe = sm501_plat_probe, .remove = sm501_plat_remove, - .suspend = sm501_plat_suspend, - .resume = sm501_plat_resume, + .suspend = pm_sleep_ptr(sm501_plat_suspend), + .resume = pm_sleep_ptr(sm501_plat_resume), }; static int __init sm501_base_init(void) { - platform_driver_register(&sm501_plat_driver); + int ret; + + ret = platform_driver_register(&sm501_plat_driver); + if (ret < 0) + return ret; + return pci_register_driver(&sm501_pci_driver); } |
