mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
Pin control changes for the v3.11 kernel cycle:
- A large slew of improvements of the Genric pin configuration support, and deployment in four different platforms: Rockchip, Super-H PFC, ABx500 and TZ1090. Support BIAS_BUS_HOLD, get device tree parsing and debugfs support into shape. - We also have device tree support with generic naming conventions for the generic pin configuration. - Delete the unused and confusing direct pinconf API. Now state transitions is *the* way to control pins and multiplexing. - New drivers for Rockchip, TZ1090, and TZ1090 PDC. - Two pin control states related to power management are now handled in the device core: "sleep" and "idle", removing a lot of boilerplate code in drivers. We do not yet know if this is the final word for pin PM, but it already make things a lot easier to handle. - Handle sparse GPIO ranges passing a list of disparate pins, and utilize these in the new BayTrail (x86 Atom SoC) driver. - Make the sunxi (AllWinner) driver handle external interrupts. - Make it possible for pinctrl-single to handle the case where several pins are managed by a single register, and augment it to handle sleep modes. - Cleanups and improvements for the abx500 drivers. - Move Sirf pin control drivers to their own directory, support save/restore of context and add support for the SiRFatlas6 SoC. - PMU muxing for the Dove pinctrl driver. - Finalization and support for VF610 in the i.MX6 pinctrl driver. - Smoothen out various Exynos rough edges. - Generic cleanups of various kinds. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQIcBAABAgAGBQJR0Z07AAoJEEEQszewGV1zx+oP/j+bh39e1Fc8ySFNvpwLFFRb EbQZx21XsK+d4fUVYQJ1IBh3e5FTqkmvHarbO1aNttqyk7eN5P4EFb3dLExIX+81 6SJYtldH5ZdvLpJNvSXAX6fUjTD1CtBCDs5z5AvDQjqUArQ2tKlzJJgFXW8MSd3B 5hd7XdU5g30GbVzFwrPbVUZwRM12YVs/HACkP6uFqDjB8KX6nXpETlqeeFW+ApvW RPT7iN/CsFls7gl6mHsPvScdfXar0ilZfu0hTf3EmhlVK1/iPOV6aqAF9z4j2Yxf ICL/x3phJ0Q7yNeZslif0KN3iJnrRGbdNvBi6wim35Ds5Uf3lY2SAhSvxNmkjT8n DB9oBTvQzr5OEv8fstWJAT+BWIdZ6Z91IqJ5Gy40A91oVUU9NDDBR3ur2gIneEUz 51kOUhucCzpiht5A/7djAx6MYYOEUwjGNzjOs7tGcxCxz4+Rb2DbAXZ3Cew45ddh 1QsfL3588A0DTp7ccw7f4QwYveX/cquzia/MD8AtdrUSYFEPfkexEo540/VqMl8j aMJ8Uuca9GSnyXDk+ziwkzLg2DjTw+p+6IygNr2GLrXFH2LTAKRpz/SidyLArDsw 0sTFan0sdU3497rHX5Xc8yCyDY4sXCdQm3/er+TE+Z7V2dS99GuEysCAInIdvM1I Wupqaxw4A25YSmbRFVpR =EbAf -----END PGP SIGNATURE----- Merge tag 'pinctrl-for-v3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl Pull pin control changes from Linus Walleij: - A large slew of improvements of the Genric pin configuration support, and deployment in four different platforms: Rockchip, Super-H PFC, ABx500 and TZ1090. Support BIAS_BUS_HOLD, get device tree parsing and debugfs support into shape. - We also have device tree support with generic naming conventions for the generic pin configuration. - Delete the unused and confusing direct pinconf API. Now state transitions is *the* way to control pins and multiplexing. - New drivers for Rockchip, TZ1090, and TZ1090 PDC. - Two pin control states related to power management are now handled in the device core: "sleep" and "idle", removing a lot of boilerplate code in drivers. We do not yet know if this is the final word for pin PM, but it already make things a lot easier to handle. - Handle sparse GPIO ranges passing a list of disparate pins, and utilize these in the new BayTrail (x86 Atom SoC) driver. - Make the sunxi (AllWinner) driver handle external interrupts. - Make it possible for pinctrl-single to handle the case where several pins are managed by a single register, and augment it to handle sleep modes. - Cleanups and improvements for the abx500 drivers. - Move Sirf pin control drivers to their own directory, support save/restore of context and add support for the SiRFatlas6 SoC. - PMU muxing for the Dove pinctrl driver. - Finalization and support for VF610 in the i.MX6 pinctrl driver. - Smoothen out various Exynos rough edges. - Generic cleanups of various kinds. * tag 'pinctrl-for-v3.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (82 commits) pinctrl: vt8500: wmt: remove redundant dev_err call in wmt_pinctrl_probe() pinctrl: remove bindings for pinconf options needing more thought pinctrl: remove slew-rate parameter from tz1090 pinctrl: set unit for debounce time pinconfig to usec pinctrl: more clarifications for generic pull configs pinctrl: rip out the direct pinconf API pinctrl-tz1090-pdc: add TZ1090 PDC pinctrl driver pinctrl-tz1090: add TZ1090 pinctrl driver pinctrl: samsung: Staticize drvdata_list pinctrl: rockchip: Add missing irq_gc_unlock() call before return error pinctrl: abx500: rework error path pinctrl: abx500: suppress hardcoded value pinctrl: abx500: factorize code pinctrl: abx500: fix abx500_gpio_get() pinctrl: abx500: fix abx500_pin_config_set() pinctrl: abx500: Add device tree support sh-pfc: Guard DT parsing with #ifdef CONFIG_OF pinctrl: add Intel BayTrail GPIO/pinctrl support pinctrl: fix pinconf_ops::pin_config_dbg_parse_modify kerneldoc pinctrl: Staticize local symbols ... Conflicts: drivers/net/ethernet/ti/davinci_mdio.c drivers/pinctrl/Makefile
This commit is contained in:
commit
3dbde57ad9
60 changed files with 12447 additions and 2945 deletions
|
|
@ -58,6 +58,18 @@ config PINCTRL_AT91
|
|||
help
|
||||
Say Y here to enable the at91 pinctrl driver
|
||||
|
||||
config PINCTRL_BAYTRAIL
|
||||
bool "Intel Baytrail GPIO pin control"
|
||||
depends on GPIOLIB && ACPI && X86
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
driver for memory mapped GPIO functionality on Intel Baytrail
|
||||
platforms. Supports 3 banks with 102, 28 and 44 gpios.
|
||||
Most pins are usually muxed to some other functionality by firmware,
|
||||
so only a small amount is available for gpio use.
|
||||
|
||||
Requires ACPI device enumeration code to set up a platform device.
|
||||
|
||||
config PINCTRL_BCM2835
|
||||
bool
|
||||
select PINMUX
|
||||
|
|
@ -108,6 +120,14 @@ config PINCTRL_IMX6SL
|
|||
help
|
||||
Say Y here to enable the imx6sl pinctrl driver
|
||||
|
||||
config PINCTRL_VF610
|
||||
bool "Freescale Vybrid VF610 pinctrl driver"
|
||||
depends on OF
|
||||
depends on SOC_VF610
|
||||
select PINCTRL_IMX
|
||||
help
|
||||
Say Y here to enable the Freescale Vybrid VF610 pinctrl driver
|
||||
|
||||
config PINCTRL_LANTIQ
|
||||
bool
|
||||
depends on LANTIQ
|
||||
|
|
@ -150,6 +170,12 @@ config PINCTRL_DB8540
|
|||
bool "DB8540 pin controller driver"
|
||||
depends on PINCTRL_NOMADIK && ARCH_U8500
|
||||
|
||||
config PINCTRL_ROCKCHIP
|
||||
bool
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
select GENERIC_IRQ_CHIP
|
||||
|
||||
config PINCTRL_SINGLE
|
||||
tristate "One-register-per-pin type device tree based pinctrl driver"
|
||||
depends on OF
|
||||
|
|
@ -192,6 +218,18 @@ config PINCTRL_TEGRA114
|
|||
bool
|
||||
select PINCTRL_TEGRA
|
||||
|
||||
config PINCTRL_TZ1090
|
||||
bool "Toumaz Xenif TZ1090 pin control driver"
|
||||
depends on SOC_TZ1090
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
|
||||
config PINCTRL_TZ1090_PDC
|
||||
bool "Toumaz Xenif TZ1090 PDC pin control driver"
|
||||
depends on SOC_TZ1090
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
|
||||
config PINCTRL_U300
|
||||
bool "U300 pin controller driver"
|
||||
depends on ARCH_U300
|
||||
|
|
|
|||
|
|
@ -16,12 +16,14 @@ obj-$(CONFIG_PINCTRL_AB9540) += pinctrl-ab9540.o
|
|||
obj-$(CONFIG_PINCTRL_AB8505) += pinctrl-ab8505.o
|
||||
obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
|
||||
obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
|
||||
obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o
|
||||
obj-$(CONFIG_PINCTRL_IMX) += pinctrl-imx.o
|
||||
obj-$(CONFIG_PINCTRL_IMX35) += pinctrl-imx35.o
|
||||
obj-$(CONFIG_PINCTRL_IMX51) += pinctrl-imx51.o
|
||||
obj-$(CONFIG_PINCTRL_IMX53) += pinctrl-imx53.o
|
||||
obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6q.o
|
||||
obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6dl.o
|
||||
obj-$(CONFIG_PINCTRL_IMX6SL) += pinctrl-imx6sl.o
|
||||
obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
|
||||
obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
|
||||
obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o
|
||||
|
|
@ -30,13 +32,16 @@ obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o
|
|||
obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o
|
||||
obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o
|
||||
obj-$(CONFIG_PINCTRL_DB8540) += pinctrl-nomadik-db8540.o
|
||||
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
|
||||
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
|
||||
obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o
|
||||
obj-$(CONFIG_PINCTRL_SIRF) += sirf/
|
||||
obj-$(CONFIG_PINCTRL_SUNXI) += pinctrl-sunxi.o
|
||||
obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o
|
||||
obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
|
||||
obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
|
||||
obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o
|
||||
obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o
|
||||
obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o
|
||||
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
|
||||
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
|
||||
obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
|
||||
|
|
@ -47,6 +52,7 @@ obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o
|
|||
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
|
||||
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
|
||||
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
|
||||
obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o
|
||||
|
||||
obj-$(CONFIG_PLAT_ORION) += mvebu/
|
||||
obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/
|
||||
|
|
|
|||
|
|
@ -41,13 +41,13 @@
|
|||
static bool pinctrl_dummy_state;
|
||||
|
||||
/* Mutex taken to protect pinctrl_list */
|
||||
DEFINE_MUTEX(pinctrl_list_mutex);
|
||||
static DEFINE_MUTEX(pinctrl_list_mutex);
|
||||
|
||||
/* Mutex taken to protect pinctrl_maps */
|
||||
DEFINE_MUTEX(pinctrl_maps_mutex);
|
||||
|
||||
/* Mutex taken to protect pinctrldev_list */
|
||||
DEFINE_MUTEX(pinctrldev_list_mutex);
|
||||
static DEFINE_MUTEX(pinctrldev_list_mutex);
|
||||
|
||||
/* Global list of pin control devices (struct pinctrl_dev) */
|
||||
static LIST_HEAD(pinctrldev_list);
|
||||
|
|
@ -101,20 +101,23 @@ EXPORT_SYMBOL_GPL(pinctrl_dev_get_drvdata);
|
|||
struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *devname)
|
||||
{
|
||||
struct pinctrl_dev *pctldev = NULL;
|
||||
bool found = false;
|
||||
|
||||
if (!devname)
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
list_for_each_entry(pctldev, &pinctrldev_list, node) {
|
||||
if (!strcmp(dev_name(pctldev->dev), devname)) {
|
||||
/* Matched on device name */
|
||||
found = true;
|
||||
break;
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return pctldev;
|
||||
}
|
||||
}
|
||||
|
||||
return found ? pctldev : NULL;
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np)
|
||||
|
|
@ -279,6 +282,29 @@ static int pinctrl_register_pins(struct pinctrl_dev *pctldev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gpio_to_pin() - GPIO range GPIO number to pin number translation
|
||||
* @range: GPIO range used for the translation
|
||||
* @gpio: gpio pin to translate to a pin number
|
||||
*
|
||||
* Finds the pin number for a given GPIO using the specified GPIO range
|
||||
* as a base for translation. The distinction between linear GPIO ranges
|
||||
* and pin list based GPIO ranges is managed correctly by this function.
|
||||
*
|
||||
* This function assumes the gpio is part of the specified GPIO range, use
|
||||
* only after making sure this is the case (e.g. by calling it on the
|
||||
* result of successful pinctrl_get_device_gpio_range calls)!
|
||||
*/
|
||||
static inline int gpio_to_pin(struct pinctrl_gpio_range *range,
|
||||
unsigned int gpio)
|
||||
{
|
||||
unsigned int offset = gpio - range->base;
|
||||
if (range->pins)
|
||||
return range->pins[offset];
|
||||
else
|
||||
return range->pin_base + offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinctrl_match_gpio_range() - check if a certain GPIO pin is in range
|
||||
* @pctldev: pin controller device to check
|
||||
|
|
@ -326,6 +352,8 @@ static bool pinctrl_ready_for_gpio_range(unsigned gpio)
|
|||
struct pinctrl_gpio_range *range = NULL;
|
||||
struct gpio_chip *chip = gpio_to_chip(gpio);
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
/* Loop over the pin controllers */
|
||||
list_for_each_entry(pctldev, &pinctrldev_list, node) {
|
||||
/* Loop over the ranges */
|
||||
|
|
@ -334,9 +362,13 @@ static bool pinctrl_ready_for_gpio_range(unsigned gpio)
|
|||
if (range->base + range->npins - 1 < chip->base ||
|
||||
range->base > chip->base + chip->ngpio - 1)
|
||||
continue;
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
|
|
@ -408,8 +440,6 @@ struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
|
|||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(devname);
|
||||
|
||||
/*
|
||||
|
|
@ -418,13 +448,10 @@ struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
|
|||
* range need to defer probing.
|
||||
*/
|
||||
if (!pctldev) {
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
pinctrl_add_gpio_range(pctldev, range);
|
||||
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
|
||||
return pctldev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range);
|
||||
|
|
@ -438,21 +465,26 @@ struct pinctrl_gpio_range *
|
|||
pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin)
|
||||
{
|
||||
struct pinctrl_gpio_range *range = NULL;
|
||||
struct pinctrl_gpio_range *range;
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
/* Loop over the ranges */
|
||||
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
|
||||
/* Check if we're in the valid range */
|
||||
if (pin >= range->pin_base &&
|
||||
pin < range->pin_base + range->npins) {
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return range;
|
||||
}
|
||||
if (range->pins) {
|
||||
int a;
|
||||
for (a = 0; a < range->npins; a++) {
|
||||
if (range->pins[a] == pin)
|
||||
goto out;
|
||||
}
|
||||
} else if (pin >= range->pin_base &&
|
||||
pin < range->pin_base + range->npins)
|
||||
goto out;
|
||||
}
|
||||
range = NULL;
|
||||
out:
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return NULL;
|
||||
return range;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin);
|
||||
|
||||
|
|
@ -517,22 +549,18 @@ int pinctrl_request_gpio(unsigned gpio)
|
|||
int ret;
|
||||
int pin;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
|
||||
if (ret) {
|
||||
if (pinctrl_ready_for_gpio_range(gpio))
|
||||
ret = 0;
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Convert to the pin controllers number space */
|
||||
pin = gpio - range->base + range->pin_base;
|
||||
pin = gpio_to_pin(range, gpio);
|
||||
|
||||
ret = pinmux_request_gpio(pctldev, range, pin, gpio);
|
||||
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_request_gpio);
|
||||
|
|
@ -552,22 +580,18 @@ void pinctrl_free_gpio(unsigned gpio)
|
|||
int ret;
|
||||
int pin;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
|
||||
if (ret) {
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return;
|
||||
}
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
/* Convert to the pin controllers number space */
|
||||
pin = gpio - range->base + range->pin_base;
|
||||
pin = gpio_to_pin(range, gpio);
|
||||
|
||||
pinmux_free_gpio(pctldev, pin, range);
|
||||
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_free_gpio);
|
||||
|
||||
|
|
@ -578,22 +602,18 @@ static int pinctrl_gpio_direction(unsigned gpio, bool input)
|
|||
int ret;
|
||||
int pin;
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
||||
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
|
||||
if (ret) {
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
/* Convert to the pin controllers number space */
|
||||
pin = gpio - range->base + range->pin_base;
|
||||
pin = gpio_to_pin(range, gpio);
|
||||
ret = pinmux_gpio_direction(pctldev, range, pin, input);
|
||||
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
mutex_unlock(&pinctrldev_list_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1204,6 +1224,69 @@ int pinctrl_force_default(struct pinctrl_dev *pctldev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_force_default);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/**
|
||||
* pinctrl_pm_select_default_state() - select default pinctrl state for PM
|
||||
* @dev: device to select default state for
|
||||
*/
|
||||
int pinctrl_pm_select_default_state(struct device *dev)
|
||||
{
|
||||
struct dev_pin_info *pins = dev->pins;
|
||||
int ret;
|
||||
|
||||
if (!pins)
|
||||
return 0;
|
||||
if (IS_ERR(pins->default_state))
|
||||
return 0; /* No default state */
|
||||
ret = pinctrl_select_state(pins->p, pins->default_state);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to activate default pinctrl state\n");
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_pm_select_default_state);
|
||||
|
||||
/**
|
||||
* pinctrl_pm_select_sleep_state() - select sleep pinctrl state for PM
|
||||
* @dev: device to select sleep state for
|
||||
*/
|
||||
int pinctrl_pm_select_sleep_state(struct device *dev)
|
||||
{
|
||||
struct dev_pin_info *pins = dev->pins;
|
||||
int ret;
|
||||
|
||||
if (!pins)
|
||||
return 0;
|
||||
if (IS_ERR(pins->sleep_state))
|
||||
return 0; /* No sleep state */
|
||||
ret = pinctrl_select_state(pins->p, pins->sleep_state);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to activate pinctrl sleep state\n");
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_pm_select_sleep_state);
|
||||
|
||||
/**
|
||||
* pinctrl_pm_select_idle_state() - select idle pinctrl state for PM
|
||||
* @dev: device to select idle state for
|
||||
*/
|
||||
int pinctrl_pm_select_idle_state(struct device *dev)
|
||||
{
|
||||
struct dev_pin_info *pins = dev->pins;
|
||||
int ret;
|
||||
|
||||
if (!pins)
|
||||
return 0;
|
||||
if (IS_ERR(pins->idle_state))
|
||||
return 0; /* No idle state */
|
||||
ret = pinctrl_select_state(pins->p, pins->idle_state);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to activate pinctrl idle state\n");
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_pm_select_idle_state);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
static int pinctrl_pins_show(struct seq_file *s, void *what)
|
||||
|
|
@ -1296,11 +1379,21 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
|
|||
|
||||
/* Loop over the ranges */
|
||||
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
|
||||
seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n",
|
||||
range->id, range->name,
|
||||
range->base, (range->base + range->npins - 1),
|
||||
range->pin_base,
|
||||
(range->pin_base + range->npins - 1));
|
||||
if (range->pins) {
|
||||
int a;
|
||||
seq_printf(s, "%u: %s GPIOS [%u - %u] PINS {",
|
||||
range->id, range->name,
|
||||
range->base, (range->base + range->npins - 1));
|
||||
for (a = 0; a < range->npins - 1; a++)
|
||||
seq_printf(s, "%u, ", range->pins[a]);
|
||||
seq_printf(s, "%u}\n", range->pins[a]);
|
||||
}
|
||||
else
|
||||
seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n",
|
||||
range->id, range->name,
|
||||
range->base, (range->base + range->npins - 1),
|
||||
range->pin_base,
|
||||
(range->pin_base + range->npins - 1));
|
||||
}
|
||||
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@
|
|||
#define DOVE_MPP_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xd0200)
|
||||
#define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10)
|
||||
#define DOVE_AU0_AC97_SEL BIT(16)
|
||||
#define DOVE_PMU_SIGNAL_SELECT_0 (DOVE_SB_REGS_VIRT_BASE + 0xd802C)
|
||||
#define DOVE_PMU_SIGNAL_SELECT_1 (DOVE_SB_REGS_VIRT_BASE + 0xd8030)
|
||||
#define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE + 0xe802C)
|
||||
#define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE + 0xe802C)
|
||||
#define DOVE_TWSI_ENABLE_OPTION1 BIT(7)
|
||||
#define DOVE_GLOBAL_CONFIG_2 (DOVE_SB_REGS_VIRT_BASE + 0xe8030)
|
||||
|
|
@ -58,12 +61,16 @@ static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
|
|||
unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
|
||||
unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
|
||||
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
|
||||
unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
|
||||
unsigned long func;
|
||||
|
||||
if (pmu & (1 << ctrl->pid))
|
||||
*config = CONFIG_PMU;
|
||||
else
|
||||
*config = (mpp >> shift) & MPP_MASK;
|
||||
if (pmu & (1 << ctrl->pid)) {
|
||||
func = readl(DOVE_PMU_SIGNAL_SELECT_0 + off);
|
||||
*config = (func >> shift) & MPP_MASK;
|
||||
*config |= CONFIG_PMU;
|
||||
} else {
|
||||
func = readl(DOVE_MPP_VIRT_BASE + off);
|
||||
*config = (func >> shift) & MPP_MASK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -73,15 +80,20 @@ static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
|
|||
unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
|
||||
unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
|
||||
unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
|
||||
unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
|
||||
unsigned long func;
|
||||
|
||||
if (config == CONFIG_PMU)
|
||||
if (config & CONFIG_PMU) {
|
||||
writel(pmu | (1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
|
||||
else {
|
||||
func = readl(DOVE_PMU_SIGNAL_SELECT_0 + off);
|
||||
func &= ~(MPP_MASK << shift);
|
||||
func |= (config & MPP_MASK) << shift;
|
||||
writel(func, DOVE_PMU_SIGNAL_SELECT_0 + off);
|
||||
} else {
|
||||
writel(pmu & ~(1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
|
||||
mpp &= ~(MPP_MASK << shift);
|
||||
mpp |= config << shift;
|
||||
writel(mpp, DOVE_MPP_VIRT_BASE + off);
|
||||
func = readl(DOVE_MPP_VIRT_BASE + off);
|
||||
func &= ~(MPP_MASK << shift);
|
||||
func |= (config & MPP_MASK) << shift;
|
||||
writel(func, DOVE_MPP_VIRT_BASE + off);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -378,20 +390,53 @@ static struct mvebu_mpp_mode dove_mpp_modes[] = {
|
|||
MPP_FUNCTION(0x02, "uart2", "rts"),
|
||||
MPP_FUNCTION(0x03, "sdio0", "cd"),
|
||||
MPP_FUNCTION(0x0f, "lcd0", "pwm"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(1,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart2", "cts"),
|
||||
MPP_FUNCTION(0x03, "sdio0", "wp"),
|
||||
MPP_FUNCTION(0x0f, "lcd1", "pwm"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(2,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x01, "sata", "prsnt"),
|
||||
MPP_FUNCTION(0x02, "uart2", "txd"),
|
||||
MPP_FUNCTION(0x03, "sdio0", "buspwr"),
|
||||
MPP_FUNCTION(0x04, "uart1", "rts"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(3,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x01, "sata", "act"),
|
||||
|
|
@ -399,43 +444,131 @@ static struct mvebu_mpp_mode dove_mpp_modes[] = {
|
|||
MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
|
||||
MPP_FUNCTION(0x04, "uart1", "cts"),
|
||||
MPP_FUNCTION(0x0f, "lcd-spi", "cs1"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(4,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart3", "rts"),
|
||||
MPP_FUNCTION(0x03, "sdio1", "cd"),
|
||||
MPP_FUNCTION(0x04, "spi1", "miso"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(5,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart3", "cts"),
|
||||
MPP_FUNCTION(0x03, "sdio1", "wp"),
|
||||
MPP_FUNCTION(0x04, "spi1", "cs"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(6,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart3", "txd"),
|
||||
MPP_FUNCTION(0x03, "sdio1", "buspwr"),
|
||||
MPP_FUNCTION(0x04, "spi1", "mosi"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(7,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart3", "rxd"),
|
||||
MPP_FUNCTION(0x03, "sdio1", "ledctrl"),
|
||||
MPP_FUNCTION(0x04, "spi1", "sck"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "core-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(8,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x01, "watchdog", "rstout"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(9,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x05, "pex1", "clkreq"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(10,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x05, "ssp", "sclk"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(11,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x01, "sata", "prsnt"),
|
||||
|
|
@ -443,33 +576,88 @@ static struct mvebu_mpp_mode dove_mpp_modes[] = {
|
|||
MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
|
||||
MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
|
||||
MPP_FUNCTION(0x05, "pex0", "clkreq"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(12,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x01, "sata", "act"),
|
||||
MPP_FUNCTION(0x02, "uart2", "rts"),
|
||||
MPP_FUNCTION(0x03, "audio0", "extclk"),
|
||||
MPP_FUNCTION(0x04, "sdio1", "cd"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(13,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart2", "cts"),
|
||||
MPP_FUNCTION(0x03, "audio1", "extclk"),
|
||||
MPP_FUNCTION(0x04, "sdio1", "wp"),
|
||||
MPP_FUNCTION(0x05, "ssp", "extclk"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(14,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart2", "txd"),
|
||||
MPP_FUNCTION(0x04, "sdio1", "buspwr"),
|
||||
MPP_FUNCTION(0x05, "ssp", "rxd"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(15,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart2", "rxd"),
|
||||
MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
|
||||
MPP_FUNCTION(0x05, "ssp", "sfrm"),
|
||||
MPP_FUNCTION(0x10, "pmu", NULL)),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x0, "pmu-nc", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x1, "pmu-low", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x2, "pmu-high", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x3, "pmic", "sdi"),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x4, "cpu-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x5, "standby-pwr-down", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0x8, "cpu-pwr-good", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xa, "bat-fault", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xb, "ext0-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xc, "ext1-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xd, "ext2-wakeup", NULL),
|
||||
MPP_FUNCTION(CONFIG_PMU | 0xe, "pmu-blink", NULL)),
|
||||
MPP_MODE(16,
|
||||
MPP_FUNCTION(0x00, "gpio", NULL),
|
||||
MPP_FUNCTION(0x02, "uart3", "rts"),
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/of.h>
|
||||
#include "core.h"
|
||||
#include "pinconf.h"
|
||||
|
||||
|
|
@ -37,14 +38,18 @@ struct pin_config_item {
|
|||
static struct pin_config_item conf_items[] = {
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_BUS_HOLD, "input bias bus hold", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
|
||||
"input bias pull to pin specific state", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_DRIVE_STRENGTH, "output drive strength", "mA"),
|
||||
PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_ENABLE, "input schmitt enabled", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"),
|
||||
PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "usec"),
|
||||
PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector"),
|
||||
PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL),
|
||||
PCONFDUMP(PIN_CONFIG_LOW_POWER_MODE, "pin low power", "mode"),
|
||||
|
|
@ -135,3 +140,100 @@ void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
struct pinconf_generic_dt_params {
|
||||
const char * const property;
|
||||
enum pin_config_param param;
|
||||
u32 default_value;
|
||||
};
|
||||
|
||||
static struct pinconf_generic_dt_params dt_params[] = {
|
||||
{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
|
||||
{ "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
|
||||
{ "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
|
||||
{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
|
||||
{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
|
||||
{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
|
||||
{ "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
|
||||
{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
|
||||
{ "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
|
||||
{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
|
||||
{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
|
||||
{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
|
||||
{ "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
|
||||
{ "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
|
||||
{ "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
|
||||
{ "output-low", PIN_CONFIG_OUTPUT, 0, },
|
||||
{ "output-high", PIN_CONFIG_OUTPUT, 1, },
|
||||
};
|
||||
|
||||
/**
|
||||
* pinconf_generic_parse_dt_config()
|
||||
* parse the config properties into generic pinconfig values.
|
||||
* @np: node containing the pinconfig properties
|
||||
* @configs: array with nconfigs entries containing the generic pinconf values
|
||||
* @nconfigs: umber of configurations
|
||||
*/
|
||||
int pinconf_generic_parse_dt_config(struct device_node *np,
|
||||
unsigned long **configs,
|
||||
unsigned int *nconfigs)
|
||||
{
|
||||
unsigned long *cfg;
|
||||
unsigned int ncfg = 0;
|
||||
int ret;
|
||||
int i;
|
||||
u32 val;
|
||||
|
||||
if (!np)
|
||||
return -EINVAL;
|
||||
|
||||
/* allocate a temporary array big enough to hold one of each option */
|
||||
cfg = kzalloc(sizeof(*cfg) * ARRAY_SIZE(dt_params), GFP_KERNEL);
|
||||
if (!cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
|
||||
struct pinconf_generic_dt_params *par = &dt_params[i];
|
||||
ret = of_property_read_u32(np, par->property, &val);
|
||||
|
||||
/* property not found */
|
||||
if (ret == -EINVAL)
|
||||
continue;
|
||||
|
||||
/* use default value, when no value is specified */
|
||||
if (ret)
|
||||
val = par->default_value;
|
||||
|
||||
pr_debug("found %s with value %u\n", par->property, val);
|
||||
cfg[ncfg] = pinconf_to_config_packed(par->param, val);
|
||||
ncfg++;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
/* no configs found at all */
|
||||
if (ncfg == 0) {
|
||||
*configs = NULL;
|
||||
*nconfigs = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now limit the number of configs to the real number of
|
||||
* found properties.
|
||||
*/
|
||||
*configs = kzalloc(ncfg * sizeof(unsigned long), GFP_KERNEL);
|
||||
if (!*configs) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(*configs, cfg, ncfg * sizeof(unsigned long));
|
||||
*nconfigs = ncfg;
|
||||
|
||||
out:
|
||||
kfree(cfg);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -75,98 +75,6 @@ int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
|
|||
return ops->pin_config_get(pctldev, pin, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* pin_config_get() - get the configuration of a single pin parameter
|
||||
* @dev_name: name of the pin controller device for this pin
|
||||
* @name: name of the pin to get the config for
|
||||
* @config: the config pointed to by this argument will be filled in with the
|
||||
* current pin state, it can be used directly by drivers as a numeral, or
|
||||
* it can be dereferenced to any struct.
|
||||
*/
|
||||
int pin_config_get(const char *dev_name, const char *name,
|
||||
unsigned long *config)
|
||||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
int pin;
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(dev_name);
|
||||
if (!pctldev) {
|
||||
pin = -EINVAL;
|
||||
return pin;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
pin = pin_get_from_name(pctldev, name);
|
||||
if (pin < 0)
|
||||
goto unlock;
|
||||
|
||||
pin = pin_config_get_for_pin(pctldev, pin, config);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return pin;
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_get);
|
||||
|
||||
static int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
unsigned long config)
|
||||
{
|
||||
const struct pinconf_ops *ops = pctldev->desc->confops;
|
||||
int ret;
|
||||
|
||||
if (!ops || !ops->pin_config_set) {
|
||||
dev_err(pctldev->dev, "cannot configure pin, missing "
|
||||
"config function in driver\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = ops->pin_config_set(pctldev, pin, config);
|
||||
if (ret) {
|
||||
dev_err(pctldev->dev,
|
||||
"unable to set pin configuration on pin %d\n", pin);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pin_config_set() - set the configuration of a single pin parameter
|
||||
* @dev_name: name of pin controller device for this pin
|
||||
* @name: name of the pin to set the config for
|
||||
* @config: the config in this argument will contain the desired pin state, it
|
||||
* can be used directly by drivers as a numeral, or it can be dereferenced
|
||||
* to any struct.
|
||||
*/
|
||||
int pin_config_set(const char *dev_name, const char *name,
|
||||
unsigned long config)
|
||||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
int pin, ret;
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(dev_name);
|
||||
if (!pctldev) {
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
pin = pin_get_from_name(pctldev, name);
|
||||
if (pin < 0) {
|
||||
ret = pin;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = pin_config_set_for_pin(pctldev, pin, config);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_set);
|
||||
|
||||
int pin_config_group_get(const char *dev_name, const char *pin_group,
|
||||
unsigned long *config)
|
||||
{
|
||||
|
|
@ -204,88 +112,6 @@ unlock:
|
|||
mutex_unlock(&pctldev->mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_group_get);
|
||||
|
||||
int pin_config_group_set(const char *dev_name, const char *pin_group,
|
||||
unsigned long config)
|
||||
{
|
||||
struct pinctrl_dev *pctldev;
|
||||
const struct pinconf_ops *ops;
|
||||
const struct pinctrl_ops *pctlops;
|
||||
int selector;
|
||||
const unsigned *pins;
|
||||
unsigned num_pins;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
pctldev = get_pinctrl_dev_from_devname(dev_name);
|
||||
if (!pctldev) {
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&pctldev->mutex);
|
||||
|
||||
ops = pctldev->desc->confops;
|
||||
pctlops = pctldev->desc->pctlops;
|
||||
|
||||
if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) {
|
||||
dev_err(pctldev->dev, "cannot configure pin group, missing "
|
||||
"config function in driver\n");
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
selector = pinctrl_get_group_selector(pctldev, pin_group);
|
||||
if (selector < 0) {
|
||||
ret = selector;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins);
|
||||
if (ret) {
|
||||
dev_err(pctldev->dev, "cannot configure pin group, error "
|
||||
"getting pins\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the pin controller supports handling entire groups we use that
|
||||
* capability.
|
||||
*/
|
||||
if (ops->pin_config_group_set) {
|
||||
ret = ops->pin_config_group_set(pctldev, selector, config);
|
||||
/*
|
||||
* If the pin controller prefer that a certain group be handled
|
||||
* pin-by-pin as well, it returns -EAGAIN.
|
||||
*/
|
||||
if (ret != -EAGAIN)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the controller cannot handle entire groups, we configure each pin
|
||||
* individually.
|
||||
*/
|
||||
if (!ops->pin_config_set) {
|
||||
ret = 0;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_pins; i++) {
|
||||
ret = ops->pin_config_set(pctldev, pins[i], config);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&pctldev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(pin_config_group_set);
|
||||
|
||||
int pinconf_map_to_setting(struct pinctrl_map const *map,
|
||||
struct pinctrl_setting *setting)
|
||||
|
|
|
|||
|
|
@ -123,3 +123,9 @@ static inline void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_OF)
|
||||
int pinconf_generic_parse_dt_config(struct device_node *np,
|
||||
unsigned long **configs,
|
||||
unsigned int *nconfigs);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,8 +30,11 @@
|
|||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
|
||||
#include "pinctrl-abx500.h"
|
||||
#include "core.h"
|
||||
#include "pinconf.h"
|
||||
|
||||
/*
|
||||
* The AB9540 and AB8540 GPIO support are extended versions
|
||||
|
|
@ -93,13 +96,15 @@
|
|||
#define AB8540_GPIOX_VBAT_START 51
|
||||
#define AB8540_GPIOX_VBAT_END 54
|
||||
|
||||
#define ABX500_GPIO_INPUT 0
|
||||
#define ABX500_GPIO_OUTPUT 1
|
||||
|
||||
struct abx500_pinctrl {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctldev;
|
||||
struct abx500_pinctrl_soc_data *soc;
|
||||
struct gpio_chip chip;
|
||||
struct ab8500 *parent;
|
||||
struct mutex lock;
|
||||
struct abx500_gpio_irq_cluster *irq_cluster;
|
||||
int irq_cluster_size;
|
||||
};
|
||||
|
|
@ -129,8 +134,8 @@ static int abx500_gpio_get_bit(struct gpio_chip *chip, u8 reg,
|
|||
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev,
|
||||
"%s read reg =%x, offset=%x failed\n",
|
||||
__func__, reg, offset);
|
||||
"%s read reg =%x, offset=%x failed (%d)\n",
|
||||
__func__, reg, offset, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -146,7 +151,8 @@ static int abx500_gpio_set_bits(struct gpio_chip *chip, u8 reg,
|
|||
ret = abx500_mask_and_set_register_interruptible(pct->dev,
|
||||
AB8500_MISC, reg, BIT(pos), val << pos);
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s write failed\n", __func__);
|
||||
dev_err(pct->dev, "%s write reg, %x offset %x failed (%d)\n",
|
||||
__func__, reg, offset, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -160,12 +166,24 @@ static int abx500_gpio_get(struct gpio_chip *chip, unsigned offset)
|
|||
{
|
||||
struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
|
||||
bool bit;
|
||||
bool is_out;
|
||||
u8 gpio_offset = offset - 1;
|
||||
int ret;
|
||||
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_IN1_REG,
|
||||
offset, &bit);
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG,
|
||||
gpio_offset, &is_out);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (is_out)
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_OUT1_REG,
|
||||
gpio_offset, &bit);
|
||||
else
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_IN1_REG,
|
||||
gpio_offset, &bit);
|
||||
out:
|
||||
if (ret < 0) {
|
||||
dev_err(pct->dev, "%s failed\n", __func__);
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -179,11 +197,47 @@ static void abx500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
|
|||
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s write failed\n", __func__);
|
||||
dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret);
|
||||
}
|
||||
|
||||
static int abx500_config_pull_updown(struct abx500_pinctrl *pct,
|
||||
int offset, enum abx500_gpio_pull_updown val)
|
||||
static int abx500_get_pull_updown(struct abx500_pinctrl *pct, int offset,
|
||||
enum abx500_gpio_pull_updown *pull_updown)
|
||||
{
|
||||
u8 pos;
|
||||
u8 val;
|
||||
int ret;
|
||||
struct pullud *pullud;
|
||||
|
||||
if (!pct->soc->pullud) {
|
||||
dev_err(pct->dev, "%s AB chip doesn't support pull up/down feature",
|
||||
__func__);
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pullud = pct->soc->pullud;
|
||||
|
||||
if ((offset < pullud->first_pin)
|
||||
|| (offset > pullud->last_pin)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = abx500_get_register_interruptible(pct->dev,
|
||||
AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG, &val);
|
||||
|
||||
pos = (offset - pullud->first_pin) << 1;
|
||||
*pull_updown = (val >> pos) & AB8540_GPIO_PULL_UPDOWN_MASK;
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int abx500_set_pull_updown(struct abx500_pinctrl *pct,
|
||||
int offset, enum abx500_gpio_pull_updown val)
|
||||
{
|
||||
u8 pos;
|
||||
int ret;
|
||||
|
|
@ -203,8 +257,7 @@ static int abx500_config_pull_updown(struct abx500_pinctrl *pct,
|
|||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pos = offset << 1;
|
||||
pos = (offset - pullud->first_pin) << 1;
|
||||
|
||||
ret = abx500_mask_and_set_register_interruptible(pct->dev,
|
||||
AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG,
|
||||
|
|
@ -217,33 +270,51 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool abx500_pullud_supported(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
|
||||
struct pullud *pullud = pct->soc->pullud;
|
||||
|
||||
return (pullud &&
|
||||
gpio >= pullud->first_pin &&
|
||||
gpio <= pullud->last_pin);
|
||||
}
|
||||
|
||||
static int abx500_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned offset,
|
||||
int val)
|
||||
{
|
||||
struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
|
||||
struct pullud *pullud = pct->soc->pullud;
|
||||
unsigned gpio;
|
||||
int ret;
|
||||
|
||||
/* set direction as output */
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 1);
|
||||
ret = abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_DIR1_REG,
|
||||
offset,
|
||||
ABX500_GPIO_OUTPUT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
/* disable pull down */
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, 1);
|
||||
ret = abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_PUD1_REG,
|
||||
offset,
|
||||
ABX500_GPIO_PULL_NONE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
/* if supported, disable both pull down and pull up */
|
||||
gpio = offset + 1;
|
||||
if (pullud && gpio >= pullud->first_pin && gpio <= pullud->last_pin) {
|
||||
ret = abx500_config_pull_updown(pct,
|
||||
if (abx500_pullud_supported(chip, gpio)) {
|
||||
ret = abx500_set_pull_updown(pct,
|
||||
gpio,
|
||||
ABX500_GPIO_PULL_NONE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
out:
|
||||
if (ret < 0) {
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set the output as 1 or 0 */
|
||||
|
|
@ -253,7 +324,10 @@ static int abx500_gpio_direction_output(struct gpio_chip *chip,
|
|||
static int abx500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
/* set the register as input */
|
||||
return abx500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 0);
|
||||
return abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_DIR1_REG,
|
||||
offset,
|
||||
ABX500_GPIO_INPUT);
|
||||
}
|
||||
|
||||
static int abx500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
|
|
@ -338,10 +412,16 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
if (af.alt_bit1 != UNUSED) {
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
|
||||
offset, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit1,
|
||||
!!(af.alta_val && BIT(0)));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (af.alt_bit2 != UNUSED)
|
||||
ret = abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_ALTFUN_REG,
|
||||
|
|
@ -355,8 +435,14 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
case ABX500_ALT_B:
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
|
||||
offset, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit1, !!(af.altb_val && BIT(0)));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (af.alt_bit2 != UNUSED)
|
||||
ret = abx500_gpio_set_bits(chip,
|
||||
AB8500_GPIO_ALTFUN_REG,
|
||||
|
|
@ -367,8 +453,14 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
case ABX500_ALT_C:
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG,
|
||||
offset, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit2, !!(af.altc_val && BIT(0)));
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit2, !!(af.altc_val && BIT(1)));
|
||||
break;
|
||||
|
|
@ -378,11 +470,14 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
|
||||
return -EINVAL;
|
||||
}
|
||||
out:
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
||||
static int abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
||||
unsigned gpio)
|
||||
{
|
||||
u8 mode;
|
||||
|
|
@ -393,6 +488,7 @@ static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
struct alternate_functions af = pct->soc->alternate_functions[gpio];
|
||||
/* on ABx5xx, there is no GPIO0, so adjust the offset */
|
||||
unsigned offset = gpio - 1;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* if gpiosel_bit is set to unused,
|
||||
|
|
@ -402,8 +498,11 @@ static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
return ABX500_DEFAULT;
|
||||
|
||||
/* read GpioSelx register */
|
||||
abx500_gpio_get_bit(chip, AB8500_GPIO_SEL1_REG + (offset / 8),
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_SEL1_REG + (offset / 8),
|
||||
af.gpiosel_bit, &bit_mode);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
mode = bit_mode;
|
||||
|
||||
/* sanity check */
|
||||
|
|
@ -435,14 +534,19 @@ static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
* pin use the AlternatFunction register
|
||||
* read alt_bit1 value
|
||||
*/
|
||||
abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit1, &alt_bit1);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (af.alt_bit2 != UNUSED)
|
||||
if (af.alt_bit2 != UNUSED) {
|
||||
/* read alt_bit2 value */
|
||||
abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG, af.alt_bit2,
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG,
|
||||
af.alt_bit2,
|
||||
&alt_bit2);
|
||||
else
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
} else
|
||||
alt_bit2 = 0;
|
||||
|
||||
mode = (alt_bit2 << 1) + alt_bit1;
|
||||
|
|
@ -452,6 +556,10 @@ static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
|
|||
return ABX500_ALT_B;
|
||||
else
|
||||
return ABX500_ALT_C;
|
||||
|
||||
out:
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
|
@ -463,11 +571,14 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
|
|||
struct gpio_chip *chip,
|
||||
unsigned offset, unsigned gpio)
|
||||
{
|
||||
struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
|
||||
const char *label = gpiochip_is_requested(chip, offset - 1);
|
||||
u8 gpio_offset = offset - 1;
|
||||
int mode = -1;
|
||||
bool is_out;
|
||||
bool pull;
|
||||
bool pd;
|
||||
enum abx500_gpio_pull_updown pud = 0;
|
||||
int ret;
|
||||
|
||||
const char *modes[] = {
|
||||
[ABX500_DEFAULT] = "default",
|
||||
|
|
@ -476,21 +587,48 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
|
|||
[ABX500_ALT_C] = "altC",
|
||||
};
|
||||
|
||||
abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG, gpio_offset, &is_out);
|
||||
abx500_gpio_get_bit(chip, AB8500_GPIO_PUD1_REG, gpio_offset, &pull);
|
||||
const char *pull_up_down[] = {
|
||||
[ABX500_GPIO_PULL_DOWN] = "pull down",
|
||||
[ABX500_GPIO_PULL_NONE] = "pull none",
|
||||
[ABX500_GPIO_PULL_NONE + 1] = "pull none",
|
||||
[ABX500_GPIO_PULL_UP] = "pull up",
|
||||
};
|
||||
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG,
|
||||
gpio_offset, &is_out);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
seq_printf(s, " gpio-%-3d (%-20.20s) %-3s",
|
||||
gpio, label ?: "(none)",
|
||||
is_out ? "out" : "in ");
|
||||
|
||||
if (!is_out) {
|
||||
if (abx500_pullud_supported(chip, offset)) {
|
||||
ret = abx500_get_pull_updown(pct, offset, &pud);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
seq_printf(s, " %-9s", pull_up_down[pud]);
|
||||
} else {
|
||||
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_PUD1_REG,
|
||||
gpio_offset, &pd);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
seq_printf(s, " %-9s", pull_up_down[pd]);
|
||||
}
|
||||
} else
|
||||
seq_printf(s, " %-9s", chip->get(chip, offset) ? "hi" : "lo");
|
||||
|
||||
if (pctldev)
|
||||
mode = abx500_get_mode(pctldev, chip, offset);
|
||||
|
||||
seq_printf(s, " gpio-%-3d (%-20.20s) %-3s %-9s %s",
|
||||
gpio, label ?: "(none)",
|
||||
is_out ? "out" : "in ",
|
||||
is_out ?
|
||||
(chip->get
|
||||
? (chip->get(chip, offset) ? "hi" : "lo")
|
||||
: "? ")
|
||||
: (pull ? "pull up" : "pull down"),
|
||||
(mode < 0) ? "unknown" : modes[mode]);
|
||||
seq_printf(s, " %s", (mode < 0) ? "unknown" : modes[mode]);
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
}
|
||||
|
||||
static void abx500_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
|
|
@ -594,6 +732,9 @@ static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
|
|||
ret = abx500_set_mode(pctldev, chip, g->pins[i], g->altsetting);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -642,10 +783,8 @@ static int abx500_gpio_request_enable(struct pinctrl_dev *pctldev,
|
|||
|
||||
ret = abx500_set_mode(pct->pctldev, &pct->chip,
|
||||
offset, p->altfunc);
|
||||
if (ret < 0) {
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s setting altfunc failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -704,11 +843,193 @@ static void abx500_pin_dbg_show(struct pinctrl_dev *pctldev,
|
|||
chip->base + offset - 1);
|
||||
}
|
||||
|
||||
static void abx500_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map, unsigned num_maps)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_maps; i++)
|
||||
if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
|
||||
kfree(map[i].data.configs.configs);
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static int abx500_dt_reserve_map(struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
unsigned *num_maps,
|
||||
unsigned reserve)
|
||||
{
|
||||
unsigned old_num = *reserved_maps;
|
||||
unsigned new_num = *num_maps + reserve;
|
||||
struct pinctrl_map *new_map;
|
||||
|
||||
if (old_num >= new_num)
|
||||
return 0;
|
||||
|
||||
new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
|
||||
if (!new_map)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
|
||||
|
||||
*map = new_map;
|
||||
*reserved_maps = new_num;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int abx500_dt_add_map_mux(struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
unsigned *num_maps, const char *group,
|
||||
const char *function)
|
||||
{
|
||||
if (*num_maps == *reserved_maps)
|
||||
return -ENOSPC;
|
||||
|
||||
(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
(*map)[*num_maps].data.mux.group = group;
|
||||
(*map)[*num_maps].data.mux.function = function;
|
||||
(*num_maps)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int abx500_dt_add_map_configs(struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
unsigned *num_maps, const char *group,
|
||||
unsigned long *configs, unsigned num_configs)
|
||||
{
|
||||
unsigned long *dup_configs;
|
||||
|
||||
if (*num_maps == *reserved_maps)
|
||||
return -ENOSPC;
|
||||
|
||||
dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
|
||||
GFP_KERNEL);
|
||||
if (!dup_configs)
|
||||
return -ENOMEM;
|
||||
|
||||
(*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN;
|
||||
|
||||
(*map)[*num_maps].data.configs.group_or_pin = group;
|
||||
(*map)[*num_maps].data.configs.configs = dup_configs;
|
||||
(*map)[*num_maps].data.configs.num_configs = num_configs;
|
||||
(*num_maps)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *abx500_find_pin_name(struct pinctrl_dev *pctldev,
|
||||
const char *pin_name)
|
||||
{
|
||||
int i, pin_number;
|
||||
struct abx500_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1)
|
||||
for (i = 0; i < npct->soc->npins; i++)
|
||||
if (npct->soc->pins[i].number == pin_number)
|
||||
return npct->soc->pins[i].name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int abx500_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
unsigned *num_maps)
|
||||
{
|
||||
int ret;
|
||||
const char *function = NULL;
|
||||
unsigned long *configs;
|
||||
unsigned int nconfigs = 0;
|
||||
bool has_config = 0;
|
||||
unsigned reserve = 0;
|
||||
struct property *prop;
|
||||
const char *group, *gpio_name;
|
||||
struct device_node *np_config;
|
||||
|
||||
ret = of_property_read_string(np, "ste,function", &function);
|
||||
if (ret >= 0)
|
||||
reserve = 1;
|
||||
|
||||
ret = pinconf_generic_parse_dt_config(np, &configs, &nconfigs);
|
||||
if (nconfigs)
|
||||
has_config = 1;
|
||||
|
||||
np_config = of_parse_phandle(np, "ste,config", 0);
|
||||
if (np_config) {
|
||||
ret = pinconf_generic_parse_dt_config(np_config, &configs,
|
||||
&nconfigs);
|
||||
if (ret)
|
||||
goto exit;
|
||||
has_config |= nconfigs;
|
||||
}
|
||||
|
||||
ret = of_property_count_strings(np, "ste,pins");
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
if (has_config)
|
||||
reserve++;
|
||||
|
||||
reserve *= ret;
|
||||
|
||||
ret = abx500_dt_reserve_map(map, reserved_maps, num_maps, reserve);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
of_property_for_each_string(np, "ste,pins", prop, group) {
|
||||
if (function) {
|
||||
ret = abx500_dt_add_map_mux(map, reserved_maps,
|
||||
num_maps, group, function);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
}
|
||||
if (has_config) {
|
||||
gpio_name = abx500_find_pin_name(pctldev, group);
|
||||
|
||||
ret = abx500_dt_add_map_configs(map, reserved_maps,
|
||||
num_maps, gpio_name, configs, 1);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
}
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int abx500_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map, unsigned *num_maps)
|
||||
{
|
||||
unsigned reserved_maps;
|
||||
struct device_node *np;
|
||||
int ret;
|
||||
|
||||
reserved_maps = 0;
|
||||
*map = NULL;
|
||||
*num_maps = 0;
|
||||
|
||||
for_each_child_of_node(np_config, np) {
|
||||
ret = abx500_dt_subnode_to_map(pctldev, np, map,
|
||||
&reserved_maps, num_maps);
|
||||
if (ret < 0) {
|
||||
abx500_dt_free_map(pctldev, *map, *num_maps);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops abx500_pinctrl_ops = {
|
||||
.get_groups_count = abx500_get_groups_cnt,
|
||||
.get_group_name = abx500_get_group_name,
|
||||
.get_group_pins = abx500_get_group_pins,
|
||||
.pin_dbg_show = abx500_pin_dbg_show,
|
||||
.dt_node_to_map = abx500_dt_node_to_map,
|
||||
.dt_free_map = abx500_dt_free_map,
|
||||
};
|
||||
|
||||
static int abx500_pin_config_get(struct pinctrl_dev *pctldev,
|
||||
|
|
@ -723,10 +1044,9 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
|
|||
unsigned long config)
|
||||
{
|
||||
struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct pullud *pullud = pct->soc->pullud;
|
||||
struct gpio_chip *chip = &pct->chip;
|
||||
unsigned offset;
|
||||
int ret;
|
||||
int ret = -EINVAL;
|
||||
enum pin_config_param param = pinconf_to_config_param(config);
|
||||
enum pin_config_param argument = pinconf_to_config_argument(config);
|
||||
|
||||
|
|
@ -739,12 +1059,10 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
|
|||
offset = pin - 1;
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
/*
|
||||
* if argument = 1 set the pull down
|
||||
* else clear the pull down
|
||||
*/
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
ret = abx500_gpio_direction_input(chip, offset);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/*
|
||||
* Some chips only support pull down, while some actually
|
||||
* support both pull up and pull down. Such chips have
|
||||
|
|
@ -752,28 +1070,72 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
|
|||
* both features. If the pin is not within that range, we
|
||||
* fall back to the old bit set that only support pull down.
|
||||
*/
|
||||
if (pullud &&
|
||||
pin >= pullud->first_pin &&
|
||||
pin <= pullud->last_pin)
|
||||
ret = abx500_config_pull_updown(pct,
|
||||
if (abx500_pullud_supported(chip, pin))
|
||||
ret = abx500_set_pull_updown(pct,
|
||||
pin,
|
||||
ABX500_GPIO_PULL_NONE);
|
||||
else
|
||||
/* Chip only supports pull down */
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG,
|
||||
offset, ABX500_GPIO_PULL_NONE);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
ret = abx500_gpio_direction_input(chip, offset);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/*
|
||||
* if argument = 1 set the pull down
|
||||
* else clear the pull down
|
||||
* Some chips only support pull down, while some actually
|
||||
* support both pull up and pull down. Such chips have
|
||||
* a "pullud" range specified for the pins that support
|
||||
* both features. If the pin is not within that range, we
|
||||
* fall back to the old bit set that only support pull down.
|
||||
*/
|
||||
if (abx500_pullud_supported(chip, pin))
|
||||
ret = abx500_set_pull_updown(pct,
|
||||
pin,
|
||||
argument ? ABX500_GPIO_PULL_DOWN : ABX500_GPIO_PULL_NONE);
|
||||
else
|
||||
/* Chip only supports pull down */
|
||||
ret = abx500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG,
|
||||
offset, argument ? 0 : 1);
|
||||
offset,
|
||||
argument ? ABX500_GPIO_PULL_DOWN : ABX500_GPIO_PULL_NONE);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
ret = abx500_gpio_direction_input(chip, offset);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/*
|
||||
* if argument = 1 set the pull up
|
||||
* else clear the pull up
|
||||
*/
|
||||
ret = abx500_gpio_direction_input(chip, offset);
|
||||
/*
|
||||
* Some chips only support pull down, while some actually
|
||||
* support both pull up and pull down. Such chips have
|
||||
* a "pullud" range specified for the pins that support
|
||||
* both features. If the pin is not within that range, do
|
||||
* nothing
|
||||
*/
|
||||
if (abx500_pullud_supported(chip, pin))
|
||||
ret = abx500_set_pull_updown(pct,
|
||||
pin,
|
||||
argument ? ABX500_GPIO_PULL_UP : ABX500_GPIO_PULL_NONE);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
ret = abx500_gpio_direction_output(chip, offset, argument);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(chip->dev, "illegal configuration requested\n");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
out:
|
||||
if (ret < 0)
|
||||
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -881,9 +1243,6 @@ static int abx500_gpio_probe(struct platform_device *pdev)
|
|||
id = (unsigned long)match->data;
|
||||
}
|
||||
|
||||
/* initialize the lock */
|
||||
mutex_init(&pct->lock);
|
||||
|
||||
/* Poke in other ASIC variants here */
|
||||
switch (id) {
|
||||
case PINCTRL_AB8500:
|
||||
|
|
@ -900,13 +1259,11 @@ static int abx500_gpio_probe(struct platform_device *pdev)
|
|||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n", id);
|
||||
mutex_destroy(&pct->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!pct->soc) {
|
||||
dev_err(&pdev->dev, "Invalid SOC data\n");
|
||||
mutex_destroy(&pct->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -917,7 +1274,6 @@ static int abx500_gpio_probe(struct platform_device *pdev)
|
|||
ret = gpiochip_add(&pct->chip);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
|
||||
mutex_destroy(&pct->lock);
|
||||
return ret;
|
||||
}
|
||||
dev_info(&pdev->dev, "added gpiochip\n");
|
||||
|
|
@ -954,7 +1310,6 @@ out_rem_chip:
|
|||
if (err)
|
||||
dev_info(&pdev->dev, "failed to remove gpiochip\n");
|
||||
|
||||
mutex_destroy(&pct->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -974,8 +1329,6 @@ static int abx500_gpio_remove(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
mutex_destroy(&pct->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1543,12 +1543,6 @@ static int at91_gpio_probe(struct platform_device *pdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -ENOENT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
|
|
@ -1561,6 +1555,7 @@ static int at91_gpio_probe(struct platform_device *pdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
at91_chip->regbase = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(at91_chip->regbase)) {
|
||||
ret = PTR_ERR(at91_chip->regbase);
|
||||
|
|
|
|||
543
drivers/pinctrl/pinctrl-baytrail.c
Normal file
543
drivers/pinctrl/pinctrl-baytrail.c
Normal file
|
|
@ -0,0 +1,543 @@
|
|||
/*
|
||||
* Pinctrl GPIO driver for Intel Baytrail
|
||||
* Copyright (c) 2012-2013, Intel Corporation.
|
||||
*
|
||||
* Author: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/acpi_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
/* memory mapped register offsets */
|
||||
#define BYT_CONF0_REG 0x000
|
||||
#define BYT_CONF1_REG 0x004
|
||||
#define BYT_VAL_REG 0x008
|
||||
#define BYT_DFT_REG 0x00c
|
||||
#define BYT_INT_STAT_REG 0x800
|
||||
|
||||
/* BYT_CONF0_REG register bits */
|
||||
#define BYT_TRIG_NEG BIT(26)
|
||||
#define BYT_TRIG_POS BIT(25)
|
||||
#define BYT_TRIG_LVL BIT(24)
|
||||
#define BYT_PIN_MUX 0x07
|
||||
|
||||
/* BYT_VAL_REG register bits */
|
||||
#define BYT_INPUT_EN BIT(2) /* 0: input enabled (active low)*/
|
||||
#define BYT_OUTPUT_EN BIT(1) /* 0: output enabled (active low)*/
|
||||
#define BYT_LEVEL BIT(0)
|
||||
|
||||
#define BYT_DIR_MASK (BIT(1) | BIT(2))
|
||||
#define BYT_TRIG_MASK (BIT(26) | BIT(25) | BIT(24))
|
||||
|
||||
#define BYT_NGPIO_SCORE 102
|
||||
#define BYT_NGPIO_NCORE 28
|
||||
#define BYT_NGPIO_SUS 44
|
||||
|
||||
/*
|
||||
* Baytrail gpio controller consist of three separate sub-controllers called
|
||||
* SCORE, NCORE and SUS. The sub-controllers are identified by their acpi UID.
|
||||
*
|
||||
* GPIO numbering is _not_ ordered meaning that gpio # 0 in ACPI namespace does
|
||||
* _not_ correspond to the first gpio register at controller's gpio base.
|
||||
* There is no logic or pattern in mapping gpio numbers to registers (pads) so
|
||||
* each sub-controller needs to have its own mapping table
|
||||
*/
|
||||
|
||||
/* score_pins[gpio_nr] = pad_nr */
|
||||
|
||||
static unsigned const score_pins[BYT_NGPIO_SCORE] = {
|
||||
85, 89, 93, 96, 99, 102, 98, 101, 34, 37,
|
||||
36, 38, 39, 35, 40, 84, 62, 61, 64, 59,
|
||||
54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
|
||||
52, 49, 48, 43, 46, 41, 45, 42, 58, 44,
|
||||
95, 105, 70, 68, 67, 66, 69, 71, 65, 72,
|
||||
86, 90, 88, 92, 103, 77, 79, 83, 78, 81,
|
||||
80, 82, 13, 12, 15, 14, 17, 18, 19, 16,
|
||||
2, 1, 0, 4, 6, 7, 9, 8, 33, 32,
|
||||
31, 30, 29, 27, 25, 28, 26, 23, 21, 20,
|
||||
24, 22, 5, 3, 10, 11, 106, 87, 91, 104,
|
||||
97, 100,
|
||||
};
|
||||
|
||||
static unsigned const ncore_pins[BYT_NGPIO_NCORE] = {
|
||||
19, 18, 17, 20, 21, 22, 24, 25, 23, 16,
|
||||
14, 15, 12, 26, 27, 1, 4, 8, 11, 0,
|
||||
3, 6, 10, 13, 2, 5, 9, 7,
|
||||
};
|
||||
|
||||
static unsigned const sus_pins[BYT_NGPIO_SUS] = {
|
||||
29, 33, 30, 31, 32, 34, 36, 35, 38, 37,
|
||||
18, 7, 11, 20, 17, 1, 8, 10, 19, 12,
|
||||
0, 2, 23, 39, 28, 27, 22, 21, 24, 25,
|
||||
26, 51, 56, 54, 49, 55, 48, 57, 50, 58,
|
||||
52, 53, 59, 40,
|
||||
};
|
||||
|
||||
static struct pinctrl_gpio_range byt_ranges[] = {
|
||||
{
|
||||
.name = "1", /* match with acpi _UID in probe */
|
||||
.npins = BYT_NGPIO_SCORE,
|
||||
.pins = score_pins,
|
||||
},
|
||||
{
|
||||
.name = "2",
|
||||
.npins = BYT_NGPIO_NCORE,
|
||||
.pins = ncore_pins,
|
||||
},
|
||||
{
|
||||
.name = "3",
|
||||
.npins = BYT_NGPIO_SUS,
|
||||
.pins = sus_pins,
|
||||
},
|
||||
{
|
||||
},
|
||||
};
|
||||
|
||||
struct byt_gpio {
|
||||
struct gpio_chip chip;
|
||||
struct irq_domain *domain;
|
||||
struct platform_device *pdev;
|
||||
spinlock_t lock;
|
||||
void __iomem *reg_base;
|
||||
struct pinctrl_gpio_range *range;
|
||||
};
|
||||
|
||||
static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
|
||||
int reg)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
u32 reg_offset;
|
||||
void __iomem *ptr;
|
||||
|
||||
if (reg == BYT_INT_STAT_REG)
|
||||
reg_offset = (offset / 32) * 4;
|
||||
else
|
||||
reg_offset = vg->range->pins[offset] * 16;
|
||||
|
||||
ptr = (void __iomem *) (vg->reg_base + reg_offset + reg);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
|
||||
pm_runtime_get(&vg->pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
|
||||
u32 value;
|
||||
|
||||
/* clear interrupt triggering */
|
||||
value = readl(reg);
|
||||
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
|
||||
writel(value, reg);
|
||||
|
||||
pm_runtime_put(&vg->pdev->dev);
|
||||
}
|
||||
|
||||
static int byt_irq_type(struct irq_data *d, unsigned type)
|
||||
{
|
||||
struct byt_gpio *vg = irq_data_get_irq_chip_data(d);
|
||||
u32 offset = irqd_to_hwirq(d);
|
||||
u32 value;
|
||||
unsigned long flags;
|
||||
void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
|
||||
|
||||
if (offset >= vg->chip.ngpio)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
value = readl(reg);
|
||||
|
||||
/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
|
||||
* are used to indicate high and low level triggering
|
||||
*/
|
||||
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
value |= BYT_TRIG_LVL;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
value |= BYT_TRIG_POS;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
value |= BYT_TRIG_LVL;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
value |= BYT_TRIG_NEG;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
|
||||
break;
|
||||
}
|
||||
writel(value, reg);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
|
||||
return readl(reg) & BYT_LEVEL;
|
||||
}
|
||||
|
||||
static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
|
||||
unsigned long flags;
|
||||
u32 old_val;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
old_val = readl(reg);
|
||||
|
||||
if (value)
|
||||
writel(old_val | BYT_LEVEL, reg);
|
||||
else
|
||||
writel(old_val & ~BYT_LEVEL, reg);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
}
|
||||
|
||||
static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
|
||||
unsigned long flags;
|
||||
u32 value;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
value = readl(reg) | BYT_DIR_MASK;
|
||||
value = value & (~BYT_INPUT_EN); /* active low */
|
||||
writel(value, reg);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int byt_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned gpio, int value)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG);
|
||||
unsigned long flags;
|
||||
u32 reg_val;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
reg_val = readl(reg) | (BYT_DIR_MASK | !!value);
|
||||
reg_val &= ~(BYT_OUTPUT_EN | !value);
|
||||
writel(reg_val, reg);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
int i;
|
||||
unsigned long flags;
|
||||
u32 conf0, val, offs;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
for (i = 0; i < vg->chip.ngpio; i++) {
|
||||
offs = vg->range->pins[i] * 16;
|
||||
conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG);
|
||||
val = readl(vg->reg_base + offs + BYT_VAL_REG);
|
||||
|
||||
seq_printf(s,
|
||||
" gpio-%-3d %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s\n",
|
||||
i,
|
||||
val & BYT_INPUT_EN ? " " : "in",
|
||||
val & BYT_OUTPUT_EN ? " " : "out",
|
||||
val & BYT_LEVEL ? "hi" : "lo",
|
||||
vg->range->pins[i], offs,
|
||||
conf0 & 0x7,
|
||||
conf0 & BYT_TRIG_NEG ? "fall " : "",
|
||||
conf0 & BYT_TRIG_POS ? "rise " : "",
|
||||
conf0 & BYT_TRIG_LVL ? "lvl " : "");
|
||||
}
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
}
|
||||
|
||||
static int byt_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip);
|
||||
return irq_create_mapping(vg->domain, offset);
|
||||
}
|
||||
|
||||
static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_data *data = irq_desc_get_irq_data(desc);
|
||||
struct byt_gpio *vg = irq_data_get_irq_handler_data(data);
|
||||
struct irq_chip *chip = irq_data_get_irq_chip(data);
|
||||
u32 base, pin, mask;
|
||||
void __iomem *reg;
|
||||
u32 pending;
|
||||
unsigned virq;
|
||||
int looplimit = 0;
|
||||
|
||||
/* check from GPIO controller which pin triggered the interrupt */
|
||||
for (base = 0; base < vg->chip.ngpio; base += 32) {
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
|
||||
|
||||
while ((pending = readl(reg))) {
|
||||
pin = __ffs(pending);
|
||||
mask = BIT(pin);
|
||||
/* Clear before handling so we can't lose an edge */
|
||||
writel(mask, reg);
|
||||
|
||||
virq = irq_find_mapping(vg->domain, base + pin);
|
||||
generic_handle_irq(virq);
|
||||
|
||||
/* In case bios or user sets triggering incorretly a pin
|
||||
* might remain in "interrupt triggered" state.
|
||||
*/
|
||||
if (looplimit++ > 32) {
|
||||
dev_err(&vg->pdev->dev,
|
||||
"Gpio %d interrupt flood, disabling\n",
|
||||
base + pin);
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, base + pin,
|
||||
BYT_CONF0_REG);
|
||||
mask = readl(reg);
|
||||
mask &= ~(BYT_TRIG_NEG | BYT_TRIG_POS |
|
||||
BYT_TRIG_LVL);
|
||||
writel(mask, reg);
|
||||
mask = readl(reg); /* flush */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
chip->irq_eoi(data);
|
||||
}
|
||||
|
||||
static void byt_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
}
|
||||
|
||||
static void byt_irq_mask(struct irq_data *d)
|
||||
{
|
||||
}
|
||||
|
||||
static struct irq_chip byt_irqchip = {
|
||||
.name = "BYT-GPIO",
|
||||
.irq_mask = byt_irq_mask,
|
||||
.irq_unmask = byt_irq_unmask,
|
||||
.irq_set_type = byt_irq_type,
|
||||
};
|
||||
|
||||
static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
|
||||
{
|
||||
void __iomem *reg;
|
||||
u32 base, value;
|
||||
|
||||
/* clear interrupt status trigger registers */
|
||||
for (base = 0; base < vg->chip.ngpio; base += 32) {
|
||||
reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
|
||||
writel(0xffffffff, reg);
|
||||
/* make sure trigger bits are cleared, if not then a pin
|
||||
might be misconfigured in bios */
|
||||
value = readl(reg);
|
||||
if (value)
|
||||
dev_err(&vg->pdev->dev,
|
||||
"GPIO interrupt error, pins misconfigured\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int byt_gpio_irq_map(struct irq_domain *d, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
struct byt_gpio *vg = d->host_data;
|
||||
|
||||
irq_set_chip_and_handler_name(virq, &byt_irqchip, handle_simple_irq,
|
||||
"demux");
|
||||
irq_set_chip_data(virq, vg);
|
||||
irq_set_irq_type(virq, IRQ_TYPE_NONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops byt_gpio_irq_ops = {
|
||||
.map = byt_gpio_irq_map,
|
||||
};
|
||||
|
||||
static int byt_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct byt_gpio *vg;
|
||||
struct gpio_chip *gc;
|
||||
struct resource *mem_rc, *irq_rc;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct acpi_device *acpi_dev;
|
||||
struct pinctrl_gpio_range *range;
|
||||
acpi_handle handle = ACPI_HANDLE(dev);
|
||||
unsigned hwirq;
|
||||
int ret;
|
||||
|
||||
if (acpi_bus_get_device(handle, &acpi_dev))
|
||||
return -ENODEV;
|
||||
|
||||
vg = devm_kzalloc(dev, sizeof(struct byt_gpio), GFP_KERNEL);
|
||||
if (!vg) {
|
||||
dev_err(&pdev->dev, "can't allocate byt_gpio chip data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (range = byt_ranges; range->name; range++) {
|
||||
if (!strcmp(acpi_dev->pnp.unique_id, range->name)) {
|
||||
vg->chip.ngpio = range->npins;
|
||||
vg->range = range;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vg->chip.ngpio || !vg->range)
|
||||
return -ENODEV;
|
||||
|
||||
vg->pdev = pdev;
|
||||
platform_set_drvdata(pdev, vg);
|
||||
|
||||
mem_rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
vg->reg_base = devm_ioremap_resource(dev, mem_rc);
|
||||
if (IS_ERR(vg->reg_base))
|
||||
return PTR_ERR(vg->reg_base);
|
||||
|
||||
spin_lock_init(&vg->lock);
|
||||
|
||||
gc = &vg->chip;
|
||||
gc->label = dev_name(&pdev->dev);
|
||||
gc->owner = THIS_MODULE;
|
||||
gc->request = byt_gpio_request;
|
||||
gc->free = byt_gpio_free;
|
||||
gc->direction_input = byt_gpio_direction_input;
|
||||
gc->direction_output = byt_gpio_direction_output;
|
||||
gc->get = byt_gpio_get;
|
||||
gc->set = byt_gpio_set;
|
||||
gc->dbg_show = byt_gpio_dbg_show;
|
||||
gc->base = -1;
|
||||
gc->can_sleep = 0;
|
||||
gc->dev = dev;
|
||||
|
||||
ret = gpiochip_add(gc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set up interrupts */
|
||||
irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (irq_rc && irq_rc->start) {
|
||||
hwirq = irq_rc->start;
|
||||
gc->to_irq = byt_gpio_to_irq;
|
||||
|
||||
vg->domain = irq_domain_add_linear(NULL, gc->ngpio,
|
||||
&byt_gpio_irq_ops, vg);
|
||||
if (!vg->domain)
|
||||
return -ENXIO;
|
||||
|
||||
byt_gpio_irq_init_hw(vg);
|
||||
|
||||
irq_set_handler_data(hwirq, vg);
|
||||
irq_set_chained_handler(hwirq, byt_gpio_irq_handler);
|
||||
|
||||
/* Register interrupt handlers for gpio signaled acpi events */
|
||||
acpi_gpiochip_request_interrupts(gc);
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int byt_gpio_runtime_suspend(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int byt_gpio_runtime_resume(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops byt_gpio_pm_ops = {
|
||||
.runtime_suspend = byt_gpio_runtime_suspend,
|
||||
.runtime_resume = byt_gpio_runtime_resume,
|
||||
};
|
||||
|
||||
static const struct acpi_device_id byt_gpio_acpi_match[] = {
|
||||
{ "INT33B2", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
|
||||
|
||||
static int byt_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct byt_gpio *vg = platform_get_drvdata(pdev);
|
||||
int err;
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
err = gpiochip_remove(&vg->chip);
|
||||
if (err)
|
||||
dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver byt_gpio_driver = {
|
||||
.probe = byt_gpio_probe,
|
||||
.remove = byt_gpio_remove,
|
||||
.driver = {
|
||||
.name = "byt_gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &byt_gpio_pm_ops,
|
||||
.acpi_match_table = ACPI_PTR(byt_gpio_acpi_match),
|
||||
},
|
||||
};
|
||||
|
||||
static int __init byt_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&byt_gpio_driver);
|
||||
}
|
||||
|
||||
subsys_initcall(byt_gpio_init);
|
||||
|
|
@ -113,7 +113,7 @@ static struct lock_class_key gpio_lock_class;
|
|||
|
||||
/* pins are just named GPIO0..GPIO53 */
|
||||
#define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
|
||||
struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
|
||||
static struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
|
||||
BCM2835_GPIO_PIN(0),
|
||||
BCM2835_GPIO_PIN(1),
|
||||
BCM2835_GPIO_PIN(2),
|
||||
|
|
|
|||
|
|
@ -853,7 +853,6 @@ static int __exit u300_gpio_remove(struct platform_device *pdev)
|
|||
}
|
||||
u300_gpio_free_ports(gpio);
|
||||
clk_disable_unprepare(gpio->clk);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,28 +50,21 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
static void exynos_gpio_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = bank->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
|
||||
unsigned long mask;
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask &= ~(1 << irqd->hwirq);
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
}
|
||||
|
||||
static void exynos_gpio_irq_mask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = bank->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
|
||||
unsigned long mask;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask |= 1 << irqd->hwirq;
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
static void exynos_gpio_irq_ack(struct irq_data *irqd)
|
||||
|
|
@ -83,6 +76,34 @@ static void exynos_gpio_irq_ack(struct irq_data *irqd)
|
|||
writel(1 << irqd->hwirq, d->virt_base + reg_pend);
|
||||
}
|
||||
|
||||
static void exynos_gpio_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = bank->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
|
||||
unsigned long mask;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Ack level interrupts right before unmask
|
||||
*
|
||||
* If we don't do this we'll get a double-interrupt. Level triggered
|
||||
* interrupts must not fire an interrupt if the level is not
|
||||
* _currently_ active, even if it was active while the interrupt was
|
||||
* masked.
|
||||
*/
|
||||
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
|
||||
exynos_gpio_irq_ack(irqd);
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask &= ~(1 << irqd->hwirq);
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
|
||||
spin_unlock_irqrestore(&bank->slock, flags);
|
||||
}
|
||||
|
||||
static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
|
|
@ -258,28 +279,21 @@ err_domains:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void exynos_wkup_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = b->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
|
||||
unsigned long mask;
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask &= ~(1 << irqd->hwirq);
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
}
|
||||
|
||||
static void exynos_wkup_irq_mask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = b->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
|
||||
unsigned long mask;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&b->slock, flags);
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask |= 1 << irqd->hwirq;
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
|
||||
spin_unlock_irqrestore(&b->slock, flags);
|
||||
}
|
||||
|
||||
static void exynos_wkup_irq_ack(struct irq_data *irqd)
|
||||
|
|
@ -291,6 +305,34 @@ static void exynos_wkup_irq_ack(struct irq_data *irqd)
|
|||
writel(1 << irqd->hwirq, d->virt_base + pend);
|
||||
}
|
||||
|
||||
static void exynos_wkup_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
|
||||
struct samsung_pinctrl_drv_data *d = b->drvdata;
|
||||
unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
|
||||
unsigned long mask;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Ack level interrupts right before unmask
|
||||
*
|
||||
* If we don't do this we'll get a double-interrupt. Level triggered
|
||||
* interrupts must not fire an interrupt if the level is not
|
||||
* _currently_ active, even if it was active while the interrupt was
|
||||
* masked.
|
||||
*/
|
||||
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
|
||||
exynos_wkup_irq_ack(irqd);
|
||||
|
||||
spin_lock_irqsave(&b->slock, flags);
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
mask &= ~(1 << irqd->hwirq);
|
||||
writel(mask, d->virt_base + reg_mask);
|
||||
|
||||
spin_unlock_irqrestore(&b->slock, flags);
|
||||
}
|
||||
|
||||
static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
{
|
||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev,
|
|||
dev_err(dev, "failed to alloc memory for group name\n");
|
||||
goto free_map;
|
||||
}
|
||||
sprintf(gname, "%s%s", np->name, GROUP_SUFFIX);
|
||||
snprintf(gname, strlen(np->name) + 4, "%s%s", np->name, GROUP_SUFFIX);
|
||||
|
||||
/*
|
||||
* don't have config options? then skip over to creating function
|
||||
|
|
@ -259,7 +259,8 @@ skip_cfgs:
|
|||
dev_err(dev, "failed to alloc memory for func name\n");
|
||||
goto free_cfg;
|
||||
}
|
||||
sprintf(fname, "%s%s", np->name, FUNCTION_SUFFIX);
|
||||
snprintf(fname, strlen(np->name) + 4, "%s%s", np->name,
|
||||
FUNCTION_SUFFIX);
|
||||
|
||||
map[*nmaps].data.mux.group = gname;
|
||||
map[*nmaps].data.mux.function = fname;
|
||||
|
|
@ -713,7 +714,8 @@ static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
|
|||
dev_err(dev, "failed to alloc memory for group name\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
sprintf(gname, "%s%s", cfg_np->name, GROUP_SUFFIX);
|
||||
snprintf(gname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
|
||||
GROUP_SUFFIX);
|
||||
|
||||
grp->name = gname;
|
||||
grp->pins = pin_list;
|
||||
|
|
@ -733,7 +735,8 @@ skip_to_pin_function:
|
|||
dev_err(dev, "failed to alloc memory for func name\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
sprintf(fname, "%s%s", cfg_np->name, FUNCTION_SUFFIX);
|
||||
snprintf(fname, strlen(cfg_np->name) + 4, "%s%s", cfg_np->name,
|
||||
FUNCTION_SUFFIX);
|
||||
|
||||
func->name = fname;
|
||||
func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL);
|
||||
|
|
@ -806,7 +809,7 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
|
|||
|
||||
/* for each pin, set the name of the pin */
|
||||
for (pin = 0; pin < ctrldesc->npins; pin++) {
|
||||
sprintf(pin_names, "gpio%02d", pin);
|
||||
snprintf(pin_names, 6, "gpio%02d", pin);
|
||||
pdesc = pindesc + pin;
|
||||
pdesc->name = pin_names;
|
||||
pin_names += PIN_NAME_LENGTH;
|
||||
|
|
|
|||
|
|
@ -221,13 +221,21 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
|
|||
pin_id = pins[i];
|
||||
pin_reg = &info->pin_regs[pin_id];
|
||||
|
||||
if (!pin_reg->mux_reg) {
|
||||
if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->mux_reg) {
|
||||
dev_err(ipctl->dev, "Pin(%s) does not support mux function\n",
|
||||
info->pins[pin_id].name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel(mux[i], ipctl->base + pin_reg->mux_reg);
|
||||
if (info->flags & SHARE_MUX_CONF_REG) {
|
||||
u32 reg;
|
||||
reg = readl(ipctl->base + pin_reg->mux_reg);
|
||||
reg &= ~(0x7 << 20);
|
||||
reg |= (mux[i] << 20);
|
||||
writel(reg, ipctl->base + pin_reg->mux_reg);
|
||||
} else {
|
||||
writel(mux[i], ipctl->base + pin_reg->mux_reg);
|
||||
}
|
||||
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
|
||||
pin_reg->mux_reg, mux[i]);
|
||||
|
||||
|
|
@ -287,7 +295,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
|
|||
const struct imx_pinctrl_soc_info *info = ipctl->info;
|
||||
const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
|
||||
|
||||
if (!pin_reg->conf_reg) {
|
||||
if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->conf_reg) {
|
||||
dev_err(info->dev, "Pin(%s) does not support config function\n",
|
||||
info->pins[pin_id].name);
|
||||
return -EINVAL;
|
||||
|
|
@ -295,6 +303,9 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
|
|||
|
||||
*config = readl(ipctl->base + pin_reg->conf_reg);
|
||||
|
||||
if (info->flags & SHARE_MUX_CONF_REG)
|
||||
*config &= 0xffff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -305,7 +316,7 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
|
|||
const struct imx_pinctrl_soc_info *info = ipctl->info;
|
||||
const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
|
||||
|
||||
if (!pin_reg->conf_reg) {
|
||||
if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->conf_reg) {
|
||||
dev_err(info->dev, "Pin(%s) does not support config function\n",
|
||||
info->pins[pin_id].name);
|
||||
return -EINVAL;
|
||||
|
|
@ -314,7 +325,15 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
|
|||
dev_dbg(ipctl->dev, "pinconf set pin %s\n",
|
||||
info->pins[pin_id].name);
|
||||
|
||||
writel(config, ipctl->base + pin_reg->conf_reg);
|
||||
if (info->flags & SHARE_MUX_CONF_REG) {
|
||||
u32 reg;
|
||||
reg = readl(ipctl->base + pin_reg->conf_reg);
|
||||
reg &= ~0xffff;
|
||||
reg |= config;
|
||||
writel(reg, ipctl->base + pin_reg->conf_reg);
|
||||
} else {
|
||||
writel(config, ipctl->base + pin_reg->conf_reg);
|
||||
}
|
||||
dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
|
||||
pin_reg->conf_reg, config);
|
||||
|
||||
|
|
@ -381,19 +400,24 @@ static struct pinctrl_desc imx_pinctrl_desc = {
|
|||
* 1 u32 CONFIG, so 24 types in total for each pin.
|
||||
*/
|
||||
#define FSL_PIN_SIZE 24
|
||||
#define SHARE_FSL_PIN_SIZE 20
|
||||
|
||||
static int imx_pinctrl_parse_groups(struct device_node *np,
|
||||
struct imx_pin_group *grp,
|
||||
struct imx_pinctrl_soc_info *info,
|
||||
u32 index)
|
||||
{
|
||||
int size;
|
||||
int size, pin_size;
|
||||
const __be32 *list;
|
||||
int i;
|
||||
u32 config;
|
||||
|
||||
dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
|
||||
|
||||
if (info->flags & SHARE_MUX_CONF_REG)
|
||||
pin_size = SHARE_FSL_PIN_SIZE;
|
||||
else
|
||||
pin_size = FSL_PIN_SIZE;
|
||||
/* Initialise group */
|
||||
grp->name = np->name;
|
||||
|
||||
|
|
@ -403,12 +427,12 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
|
|||
*/
|
||||
list = of_get_property(np, "fsl,pins", &size);
|
||||
/* we do not check return since it's safe node passed down */
|
||||
if (!size || size % FSL_PIN_SIZE) {
|
||||
if (!size || size % pin_size) {
|
||||
dev_err(info->dev, "Invalid fsl,pins property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
grp->npins = size / FSL_PIN_SIZE;
|
||||
grp->npins = size / pin_size;
|
||||
grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
|
||||
GFP_KERNEL);
|
||||
grp->mux_mode = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
|
||||
|
|
@ -421,10 +445,17 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
|
|||
GFP_KERNEL);
|
||||
for (i = 0; i < grp->npins; i++) {
|
||||
u32 mux_reg = be32_to_cpu(*list++);
|
||||
u32 conf_reg = be32_to_cpu(*list++);
|
||||
unsigned int pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4;
|
||||
struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
|
||||
u32 conf_reg;
|
||||
unsigned int pin_id;
|
||||
struct imx_pin_reg *pin_reg;
|
||||
|
||||
if (info->flags & SHARE_MUX_CONF_REG)
|
||||
conf_reg = mux_reg;
|
||||
else
|
||||
conf_reg = be32_to_cpu(*list++);
|
||||
|
||||
pin_id = mux_reg ? mux_reg / 4 : conf_reg / 4;
|
||||
pin_reg = &info->pin_regs[pin_id];
|
||||
grp->pins[i] = pin_id;
|
||||
pin_reg->mux_reg = mux_reg;
|
||||
pin_reg->conf_reg = conf_reg;
|
||||
|
|
|
|||
|
|
@ -74,8 +74,12 @@ struct imx_pinctrl_soc_info {
|
|||
unsigned int ngroups;
|
||||
struct imx_pmx_func *functions;
|
||||
unsigned int nfunctions;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#define ZERO_OFFSET_VALID 0x1
|
||||
#define SHARE_MUX_CONF_REG 0x2
|
||||
|
||||
#define NO_MUX 0x0
|
||||
#define NO_PAD 0x0
|
||||
|
||||
|
|
|
|||
|
|
@ -515,7 +515,6 @@ int mxs_pinctrl_probe(struct platform_device *pdev,
|
|||
return 0;
|
||||
|
||||
err:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
iounmap(d->base);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -525,7 +524,6 @@ int mxs_pinctrl_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
pinctrl_unregister(d->pctl);
|
||||
iounmap(d->base);
|
||||
|
||||
|
|
|
|||
|
|
@ -1309,7 +1309,7 @@ static int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq,
|
|||
return 0;
|
||||
}
|
||||
|
||||
const struct irq_domain_ops nmk_gpio_irq_simple_ops = {
|
||||
static const struct irq_domain_ops nmk_gpio_irq_simple_ops = {
|
||||
.map = nmk_gpio_irq_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
|
@ -1681,7 +1681,7 @@ static bool nmk_pinctrl_dt_get_config(struct device_node *np,
|
|||
return has_config;
|
||||
}
|
||||
|
||||
int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
static int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
|
|
@ -1740,7 +1740,7 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
static int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map, unsigned *num_maps)
|
||||
{
|
||||
|
|
|
|||
1394
drivers/pinctrl/pinctrl-rockchip.c
Normal file
1394
drivers/pinctrl/pinctrl-rockchip.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -50,7 +50,7 @@ static struct pin_config {
|
|||
};
|
||||
|
||||
/* Global list of devices (struct samsung_pinctrl_drv_data) */
|
||||
LIST_HEAD(drvdata_list);
|
||||
static LIST_HEAD(drvdata_list);
|
||||
|
||||
static unsigned int pin_base;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#define DRIVER_NAME "pinctrl-single"
|
||||
#define PCS_MUX_PINS_NAME "pinctrl-single,pins"
|
||||
#define PCS_MUX_BITS_NAME "pinctrl-single,bits"
|
||||
#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1)
|
||||
#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 3)
|
||||
#define PCS_OFF_DISABLED ~0U
|
||||
|
||||
/**
|
||||
|
|
@ -163,6 +163,7 @@ struct pcs_name {
|
|||
* @foff: value to turn mux off
|
||||
* @fmax: max number of functions in fmask
|
||||
* @is_pinconf: whether supports pinconf
|
||||
* @bits_per_pin:number of bits per pin
|
||||
* @names: array of register names for pins
|
||||
* @pins: physical pins on the SoC
|
||||
* @pgtree: pingroup index radix tree
|
||||
|
|
@ -190,6 +191,7 @@ struct pcs_device {
|
|||
unsigned fmax;
|
||||
bool bits_per_mux;
|
||||
bool is_pinconf;
|
||||
unsigned bits_per_pin;
|
||||
struct pcs_name *names;
|
||||
struct pcs_data pins;
|
||||
struct radix_tree_root pgtree;
|
||||
|
|
@ -431,10 +433,11 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
|
|||
|
||||
vals = &func->vals[i];
|
||||
val = pcs->read(vals->reg);
|
||||
if (!vals->mask)
|
||||
mask = pcs->fmask;
|
||||
|
||||
if (pcs->bits_per_mux)
|
||||
mask = vals->mask;
|
||||
else
|
||||
mask = pcs->fmask & vals->mask;
|
||||
mask = pcs->fmask;
|
||||
|
||||
val &= ~mask;
|
||||
val |= (vals->val & mask);
|
||||
|
|
@ -741,7 +744,8 @@ static const struct pinconf_ops pcs_pinconf_ops = {
|
|||
* @pcs: pcs driver instance
|
||||
* @offset: register offset from base
|
||||
*/
|
||||
static int pcs_add_pin(struct pcs_device *pcs, unsigned offset)
|
||||
static int pcs_add_pin(struct pcs_device *pcs, unsigned offset,
|
||||
unsigned pin_pos)
|
||||
{
|
||||
struct pinctrl_pin_desc *pin;
|
||||
struct pcs_name *pn;
|
||||
|
|
@ -756,8 +760,8 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset)
|
|||
|
||||
pin = &pcs->pins.pa[i];
|
||||
pn = &pcs->names[i];
|
||||
sprintf(pn->name, "%lx",
|
||||
(unsigned long)pcs->res->start + offset);
|
||||
sprintf(pn->name, "%lx.%d",
|
||||
(unsigned long)pcs->res->start + offset, pin_pos);
|
||||
pin->name = pn->name;
|
||||
pin->number = i;
|
||||
pcs->pins.cur++;
|
||||
|
|
@ -777,9 +781,17 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset)
|
|||
static int pcs_allocate_pin_table(struct pcs_device *pcs)
|
||||
{
|
||||
int mux_bytes, nr_pins, i;
|
||||
int num_pins_in_register = 0;
|
||||
|
||||
mux_bytes = pcs->width / BITS_PER_BYTE;
|
||||
nr_pins = pcs->size / mux_bytes;
|
||||
|
||||
if (pcs->bits_per_mux) {
|
||||
pcs->bits_per_pin = fls(pcs->fmask);
|
||||
nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin;
|
||||
num_pins_in_register = pcs->width / pcs->bits_per_pin;
|
||||
} else {
|
||||
nr_pins = pcs->size / mux_bytes;
|
||||
}
|
||||
|
||||
dev_dbg(pcs->dev, "allocating %i pins\n", nr_pins);
|
||||
pcs->pins.pa = devm_kzalloc(pcs->dev,
|
||||
|
|
@ -800,9 +812,17 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
|
|||
for (i = 0; i < pcs->desc.npins; i++) {
|
||||
unsigned offset;
|
||||
int res;
|
||||
int byte_num;
|
||||
int pin_pos = 0;
|
||||
|
||||
offset = i * mux_bytes;
|
||||
res = pcs_add_pin(pcs, offset);
|
||||
if (pcs->bits_per_mux) {
|
||||
byte_num = (pcs->bits_per_pin * i) / BITS_PER_BYTE;
|
||||
offset = (byte_num / mux_bytes) * mux_bytes;
|
||||
pin_pos = i % num_pins_in_register;
|
||||
} else {
|
||||
offset = i * mux_bytes;
|
||||
}
|
||||
res = pcs_add_pin(pcs, offset, pin_pos);
|
||||
if (res < 0) {
|
||||
dev_err(pcs->dev, "error adding pins: %i\n", res);
|
||||
return res;
|
||||
|
|
@ -919,7 +939,10 @@ static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
index = offset / (pcs->width / BITS_PER_BYTE);
|
||||
if (pcs->bits_per_mux)
|
||||
index = (offset * BITS_PER_BYTE) / pcs->bits_per_pin;
|
||||
else
|
||||
index = offset / (pcs->width / BITS_PER_BYTE);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
|
@ -1097,29 +1120,18 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
|
|||
{
|
||||
struct pcs_func_vals *vals;
|
||||
const __be32 *mux;
|
||||
int size, params, rows, *pins, index = 0, found = 0, res = -ENOMEM;
|
||||
int size, rows, *pins, index = 0, found = 0, res = -ENOMEM;
|
||||
struct pcs_function *function;
|
||||
|
||||
if (pcs->bits_per_mux) {
|
||||
params = 3;
|
||||
mux = of_get_property(np, PCS_MUX_BITS_NAME, &size);
|
||||
} else {
|
||||
params = 2;
|
||||
mux = of_get_property(np, PCS_MUX_PINS_NAME, &size);
|
||||
}
|
||||
|
||||
if (!mux) {
|
||||
dev_err(pcs->dev, "no valid property for %s\n", np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (size < (sizeof(*mux) * params)) {
|
||||
dev_err(pcs->dev, "bad data for %s\n", np->name);
|
||||
mux = of_get_property(np, PCS_MUX_PINS_NAME, &size);
|
||||
if ((!mux) || (size < sizeof(*mux) * 2)) {
|
||||
dev_err(pcs->dev, "bad data for mux %s\n",
|
||||
np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size /= sizeof(*mux); /* Number of elements in array */
|
||||
rows = size / params;
|
||||
rows = size / 2;
|
||||
|
||||
vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL);
|
||||
if (!vals)
|
||||
|
|
@ -1137,10 +1149,6 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
|
|||
val = be32_to_cpup(mux + index++);
|
||||
vals[found].reg = pcs->base + offset;
|
||||
vals[found].val = val;
|
||||
if (params == 3) {
|
||||
val = be32_to_cpup(mux + index++);
|
||||
vals[found].mask = val;
|
||||
}
|
||||
|
||||
pin = pcs_get_pin_by_offset(pcs, offset);
|
||||
if (pin < 0) {
|
||||
|
|
@ -1184,6 +1192,125 @@ free_function:
|
|||
free_pins:
|
||||
devm_kfree(pcs->dev, pins);
|
||||
|
||||
free_vals:
|
||||
devm_kfree(pcs->dev, vals);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define PARAMS_FOR_BITS_PER_MUX 3
|
||||
|
||||
static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *num_maps,
|
||||
const char **pgnames)
|
||||
{
|
||||
struct pcs_func_vals *vals;
|
||||
const __be32 *mux;
|
||||
int size, rows, *pins, index = 0, found = 0, res = -ENOMEM;
|
||||
int npins_in_row;
|
||||
struct pcs_function *function;
|
||||
|
||||
mux = of_get_property(np, PCS_MUX_BITS_NAME, &size);
|
||||
|
||||
if (!mux) {
|
||||
dev_err(pcs->dev, "no valid property for %s\n", np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (size < (sizeof(*mux) * PARAMS_FOR_BITS_PER_MUX)) {
|
||||
dev_err(pcs->dev, "bad data for %s\n", np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Number of elements in array */
|
||||
size /= sizeof(*mux);
|
||||
|
||||
rows = size / PARAMS_FOR_BITS_PER_MUX;
|
||||
npins_in_row = pcs->width / pcs->bits_per_pin;
|
||||
|
||||
vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows * npins_in_row,
|
||||
GFP_KERNEL);
|
||||
if (!vals)
|
||||
return -ENOMEM;
|
||||
|
||||
pins = devm_kzalloc(pcs->dev, sizeof(*pins) * rows * npins_in_row,
|
||||
GFP_KERNEL);
|
||||
if (!pins)
|
||||
goto free_vals;
|
||||
|
||||
while (index < size) {
|
||||
unsigned offset, val;
|
||||
unsigned mask, bit_pos, val_pos, mask_pos, submask;
|
||||
unsigned pin_num_from_lsb;
|
||||
int pin;
|
||||
|
||||
offset = be32_to_cpup(mux + index++);
|
||||
val = be32_to_cpup(mux + index++);
|
||||
mask = be32_to_cpup(mux + index++);
|
||||
|
||||
/* Parse pins in each row from LSB */
|
||||
while (mask) {
|
||||
bit_pos = ffs(mask);
|
||||
pin_num_from_lsb = bit_pos / pcs->bits_per_pin;
|
||||
mask_pos = ((pcs->fmask) << (bit_pos - 1));
|
||||
val_pos = val & mask_pos;
|
||||
submask = mask & mask_pos;
|
||||
mask &= ~mask_pos;
|
||||
|
||||
if (submask != mask_pos) {
|
||||
dev_warn(pcs->dev,
|
||||
"Invalid submask 0x%x for %s at 0x%x\n",
|
||||
submask, np->name, offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
vals[found].mask = submask;
|
||||
vals[found].reg = pcs->base + offset;
|
||||
vals[found].val = val_pos;
|
||||
|
||||
pin = pcs_get_pin_by_offset(pcs, offset);
|
||||
if (pin < 0) {
|
||||
dev_err(pcs->dev,
|
||||
"could not add functions for %s %ux\n",
|
||||
np->name, offset);
|
||||
break;
|
||||
}
|
||||
pins[found++] = pin + pin_num_from_lsb;
|
||||
}
|
||||
}
|
||||
|
||||
pgnames[0] = np->name;
|
||||
function = pcs_add_function(pcs, np, np->name, vals, found, pgnames, 1);
|
||||
if (!function)
|
||||
goto free_pins;
|
||||
|
||||
res = pcs_add_pingroup(pcs, np, np->name, pins, found);
|
||||
if (res < 0)
|
||||
goto free_function;
|
||||
|
||||
(*map)->type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
(*map)->data.mux.group = np->name;
|
||||
(*map)->data.mux.function = np->name;
|
||||
|
||||
if (pcs->is_pinconf) {
|
||||
dev_err(pcs->dev, "pinconf not supported\n");
|
||||
goto free_pingroups;
|
||||
}
|
||||
|
||||
*num_maps = 1;
|
||||
return 0;
|
||||
|
||||
free_pingroups:
|
||||
pcs_free_pingroups(pcs);
|
||||
*num_maps = 1;
|
||||
free_function:
|
||||
pcs_remove_function(pcs, function);
|
||||
|
||||
free_pins:
|
||||
devm_kfree(pcs->dev, pins);
|
||||
|
||||
free_vals:
|
||||
devm_kfree(pcs->dev, vals);
|
||||
|
||||
|
|
@ -1219,12 +1346,22 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
|
|||
goto free_map;
|
||||
}
|
||||
|
||||
ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, num_maps,
|
||||
pgnames);
|
||||
if (ret < 0) {
|
||||
dev_err(pcs->dev, "no pins entries for %s\n",
|
||||
np_config->name);
|
||||
goto free_pgnames;
|
||||
if (pcs->bits_per_mux) {
|
||||
ret = pcs_parse_bits_in_pinctrl_entry(pcs, np_config, map,
|
||||
num_maps, pgnames);
|
||||
if (ret < 0) {
|
||||
dev_err(pcs->dev, "no pins entries for %s\n",
|
||||
np_config->name);
|
||||
goto free_pgnames;
|
||||
}
|
||||
} else {
|
||||
ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map,
|
||||
num_maps, pgnames);
|
||||
if (ret < 0) {
|
||||
dev_err(pcs->dev, "no pins entries for %s\n",
|
||||
np_config->name);
|
||||
goto free_pgnames;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1346,6 +1483,29 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int pinctrl_single_suspend(struct platform_device *pdev,
|
||||
pm_message_t state)
|
||||
{
|
||||
struct pcs_device *pcs;
|
||||
|
||||
pcs = platform_get_drvdata(pdev);
|
||||
if (!pcs)
|
||||
return -EINVAL;
|
||||
|
||||
return pinctrl_force_sleep(pcs->pctl);
|
||||
}
|
||||
|
||||
static int pinctrl_single_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct pcs_device *pcs;
|
||||
|
||||
pcs = platform_get_drvdata(pdev);
|
||||
if (!pcs)
|
||||
return -EINVAL;
|
||||
|
||||
return pinctrl_force_default(pcs->pctl);
|
||||
}
|
||||
|
||||
static int pcs_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
|
@ -1494,6 +1654,10 @@ static struct platform_driver pcs_driver = {
|
|||
.name = DRIVER_NAME,
|
||||
.of_match_table = pcs_of_match,
|
||||
},
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = pinctrl_single_suspend,
|
||||
.resume = pinctrl_single_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
module_platform_driver(pcs_driver);
|
||||
|
|
|
|||
2023
drivers/pinctrl/pinctrl-sunxi-pins.h
Normal file
2023
drivers/pinctrl/pinctrl-sunxi-pins.h
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -344,9 +344,31 @@
|
|||
#define PULL_PINS_BITS 2
|
||||
#define PULL_PINS_MASK 0x03
|
||||
|
||||
#define SUNXI_IRQ_NUMBER 32
|
||||
|
||||
#define IRQ_CFG_REG 0x200
|
||||
#define IRQ_CFG_IRQ_PER_REG 8
|
||||
#define IRQ_CFG_IRQ_BITS 4
|
||||
#define IRQ_CFG_IRQ_MASK ((1 << IRQ_CFG_IRQ_BITS) - 1)
|
||||
#define IRQ_CTRL_REG 0x210
|
||||
#define IRQ_CTRL_IRQ_PER_REG 32
|
||||
#define IRQ_CTRL_IRQ_BITS 1
|
||||
#define IRQ_CTRL_IRQ_MASK ((1 << IRQ_CTRL_IRQ_BITS) - 1)
|
||||
#define IRQ_STATUS_REG 0x214
|
||||
#define IRQ_STATUS_IRQ_PER_REG 32
|
||||
#define IRQ_STATUS_IRQ_BITS 1
|
||||
#define IRQ_STATUS_IRQ_MASK ((1 << IRQ_STATUS_IRQ_BITS) - 1)
|
||||
|
||||
#define IRQ_EDGE_RISING 0x00
|
||||
#define IRQ_EDGE_FALLING 0x01
|
||||
#define IRQ_LEVEL_HIGH 0x02
|
||||
#define IRQ_LEVEL_LOW 0x03
|
||||
#define IRQ_EDGE_BOTH 0x04
|
||||
|
||||
struct sunxi_desc_function {
|
||||
const char *name;
|
||||
u8 muxval;
|
||||
u8 irqnum;
|
||||
};
|
||||
|
||||
struct sunxi_desc_pin {
|
||||
|
|
@ -378,10 +400,13 @@ struct sunxi_pinctrl {
|
|||
struct gpio_chip *chip;
|
||||
struct sunxi_pinctrl_desc *desc;
|
||||
struct device *dev;
|
||||
struct irq_domain *domain;
|
||||
struct sunxi_pinctrl_function *functions;
|
||||
unsigned nfunctions;
|
||||
struct sunxi_pinctrl_group *groups;
|
||||
unsigned ngroups;
|
||||
int irq;
|
||||
int irq_array[SUNXI_IRQ_NUMBER];
|
||||
struct pinctrl_dev *pctl_dev;
|
||||
};
|
||||
|
||||
|
|
@ -398,6 +423,13 @@ struct sunxi_pinctrl {
|
|||
.muxval = _val, \
|
||||
}
|
||||
|
||||
#define SUNXI_FUNCTION_IRQ(_val, _irq) \
|
||||
{ \
|
||||
.name = "irq", \
|
||||
.muxval = _val, \
|
||||
.irqnum = _irq, \
|
||||
}
|
||||
|
||||
/*
|
||||
* The sunXi PIO registers are organized as is:
|
||||
* 0x00 - 0x0c Muxing values.
|
||||
|
|
@ -475,4 +507,40 @@ static inline u32 sunxi_pull_offset(u16 pin)
|
|||
return pin_num * PULL_PINS_BITS;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_cfg_reg(u16 irq)
|
||||
{
|
||||
u8 reg = irq / IRQ_CFG_IRQ_PER_REG;
|
||||
return reg + IRQ_CFG_REG;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_cfg_offset(u16 irq)
|
||||
{
|
||||
u32 irq_num = irq % IRQ_CFG_IRQ_PER_REG;
|
||||
return irq_num * IRQ_CFG_IRQ_BITS;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_ctrl_reg(u16 irq)
|
||||
{
|
||||
u8 reg = irq / IRQ_CTRL_IRQ_PER_REG;
|
||||
return reg + IRQ_CTRL_REG;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_ctrl_offset(u16 irq)
|
||||
{
|
||||
u32 irq_num = irq % IRQ_CTRL_IRQ_PER_REG;
|
||||
return irq_num * IRQ_CTRL_IRQ_BITS;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_status_reg(u16 irq)
|
||||
{
|
||||
u8 reg = irq / IRQ_STATUS_IRQ_PER_REG;
|
||||
return reg + IRQ_STATUS_REG;
|
||||
}
|
||||
|
||||
static inline u32 sunxi_irq_status_offset(u16 irq)
|
||||
{
|
||||
u32 irq_num = irq % IRQ_STATUS_IRQ_PER_REG;
|
||||
return irq_num * IRQ_STATUS_IRQ_BITS;
|
||||
}
|
||||
|
||||
#endif /* __PINCTRL_SUNXI_H */
|
||||
|
|
|
|||
1024
drivers/pinctrl/pinctrl-tz1090-pdc.c
Normal file
1024
drivers/pinctrl/pinctrl-tz1090-pdc.c
Normal file
File diff suppressed because it is too large
Load diff
2072
drivers/pinctrl/pinctrl-tz1090.c
Normal file
2072
drivers/pinctrl/pinctrl-tz1090.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1100,7 +1100,6 @@ static int u300_pmx_remove(struct platform_device *pdev)
|
|||
struct u300_pmx *upmx = platform_get_drvdata(pdev);
|
||||
|
||||
pinctrl_unregister(upmx->pctl);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
338
drivers/pinctrl/pinctrl-vf610.c
Normal file
338
drivers/pinctrl/pinctrl-vf610.c
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
* VF610 pinctrl driver based on imx pinmux and pinconf core
|
||||
*
|
||||
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-imx.h"
|
||||
|
||||
enum vf610_pads {
|
||||
VF610_PAD_PTA6 = 0,
|
||||
VF610_PAD_PTA8 = 1,
|
||||
VF610_PAD_PTA9 = 2,
|
||||
VF610_PAD_PTA10 = 3,
|
||||
VF610_PAD_PTA11 = 4,
|
||||
VF610_PAD_PTA12 = 5,
|
||||
VF610_PAD_PTA16 = 6,
|
||||
VF610_PAD_PTA17 = 7,
|
||||
VF610_PAD_PTA18 = 8,
|
||||
VF610_PAD_PTA19 = 9,
|
||||
VF610_PAD_PTA20 = 10,
|
||||
VF610_PAD_PTA21 = 11,
|
||||
VF610_PAD_PTA22 = 12,
|
||||
VF610_PAD_PTA23 = 13,
|
||||
VF610_PAD_PTA24 = 14,
|
||||
VF610_PAD_PTA25 = 15,
|
||||
VF610_PAD_PTA26 = 16,
|
||||
VF610_PAD_PTA27 = 17,
|
||||
VF610_PAD_PTA28 = 18,
|
||||
VF610_PAD_PTA29 = 19,
|
||||
VF610_PAD_PTA30 = 20,
|
||||
VF610_PAD_PTA31 = 21,
|
||||
VF610_PAD_PTB0 = 22,
|
||||
VF610_PAD_PTB1 = 23,
|
||||
VF610_PAD_PTB2 = 24,
|
||||
VF610_PAD_PTB3 = 25,
|
||||
VF610_PAD_PTB4 = 26,
|
||||
VF610_PAD_PTB5 = 27,
|
||||
VF610_PAD_PTB6 = 28,
|
||||
VF610_PAD_PTB7 = 29,
|
||||
VF610_PAD_PTB8 = 30,
|
||||
VF610_PAD_PTB9 = 31,
|
||||
VF610_PAD_PTB10 = 32,
|
||||
VF610_PAD_PTB11 = 33,
|
||||
VF610_PAD_PTB12 = 34,
|
||||
VF610_PAD_PTB13 = 35,
|
||||
VF610_PAD_PTB14 = 36,
|
||||
VF610_PAD_PTB15 = 37,
|
||||
VF610_PAD_PTB16 = 38,
|
||||
VF610_PAD_PTB17 = 39,
|
||||
VF610_PAD_PTB18 = 40,
|
||||
VF610_PAD_PTB19 = 41,
|
||||
VF610_PAD_PTB20 = 42,
|
||||
VF610_PAD_PTB21 = 43,
|
||||
VF610_PAD_PTB22 = 44,
|
||||
VF610_PAD_PTC0 = 45,
|
||||
VF610_PAD_PTC1 = 46,
|
||||
VF610_PAD_PTC2 = 47,
|
||||
VF610_PAD_PTC3 = 48,
|
||||
VF610_PAD_PTC4 = 49,
|
||||
VF610_PAD_PTC5 = 50,
|
||||
VF610_PAD_PTC6 = 51,
|
||||
VF610_PAD_PTC7 = 52,
|
||||
VF610_PAD_PTC8 = 53,
|
||||
VF610_PAD_PTC9 = 54,
|
||||
VF610_PAD_PTC10 = 55,
|
||||
VF610_PAD_PTC11 = 56,
|
||||
VF610_PAD_PTC12 = 57,
|
||||
VF610_PAD_PTC13 = 58,
|
||||
VF610_PAD_PTC14 = 59,
|
||||
VF610_PAD_PTC15 = 60,
|
||||
VF610_PAD_PTC16 = 61,
|
||||
VF610_PAD_PTC17 = 62,
|
||||
VF610_PAD_PTD31 = 63,
|
||||
VF610_PAD_PTD30 = 64,
|
||||
VF610_PAD_PTD29 = 65,
|
||||
VF610_PAD_PTD28 = 66,
|
||||
VF610_PAD_PTD27 = 67,
|
||||
VF610_PAD_PTD26 = 68,
|
||||
VF610_PAD_PTD25 = 69,
|
||||
VF610_PAD_PTD24 = 70,
|
||||
VF610_PAD_PTD23 = 71,
|
||||
VF610_PAD_PTD22 = 72,
|
||||
VF610_PAD_PTD21 = 73,
|
||||
VF610_PAD_PTD20 = 74,
|
||||
VF610_PAD_PTD19 = 75,
|
||||
VF610_PAD_PTD18 = 76,
|
||||
VF610_PAD_PTD17 = 77,
|
||||
VF610_PAD_PTD16 = 78,
|
||||
VF610_PAD_PTD0 = 79,
|
||||
VF610_PAD_PTD1 = 80,
|
||||
VF610_PAD_PTD2 = 81,
|
||||
VF610_PAD_PTD3 = 82,
|
||||
VF610_PAD_PTD4 = 83,
|
||||
VF610_PAD_PTD5 = 84,
|
||||
VF610_PAD_PTD6 = 85,
|
||||
VF610_PAD_PTD7 = 86,
|
||||
VF610_PAD_PTD8 = 87,
|
||||
VF610_PAD_PTD9 = 88,
|
||||
VF610_PAD_PTD10 = 89,
|
||||
VF610_PAD_PTD11 = 90,
|
||||
VF610_PAD_PTD12 = 91,
|
||||
VF610_PAD_PTD13 = 92,
|
||||
VF610_PAD_PTB23 = 93,
|
||||
VF610_PAD_PTB24 = 94,
|
||||
VF610_PAD_PTB25 = 95,
|
||||
VF610_PAD_PTB26 = 96,
|
||||
VF610_PAD_PTB27 = 97,
|
||||
VF610_PAD_PTB28 = 98,
|
||||
VF610_PAD_PTC26 = 99,
|
||||
VF610_PAD_PTC27 = 100,
|
||||
VF610_PAD_PTC28 = 101,
|
||||
VF610_PAD_PTC29 = 102,
|
||||
VF610_PAD_PTC30 = 103,
|
||||
VF610_PAD_PTC31 = 104,
|
||||
VF610_PAD_PTE0 = 105,
|
||||
VF610_PAD_PTE1 = 106,
|
||||
VF610_PAD_PTE2 = 107,
|
||||
VF610_PAD_PTE3 = 108,
|
||||
VF610_PAD_PTE4 = 109,
|
||||
VF610_PAD_PTE5 = 110,
|
||||
VF610_PAD_PTE6 = 111,
|
||||
VF610_PAD_PTE7 = 112,
|
||||
VF610_PAD_PTE8 = 113,
|
||||
VF610_PAD_PTE9 = 114,
|
||||
VF610_PAD_PTE10 = 115,
|
||||
VF610_PAD_PTE11 = 116,
|
||||
VF610_PAD_PTE12 = 117,
|
||||
VF610_PAD_PTE13 = 118,
|
||||
VF610_PAD_PTE14 = 119,
|
||||
VF610_PAD_PTE15 = 120,
|
||||
VF610_PAD_PTE16 = 121,
|
||||
VF610_PAD_PTE17 = 122,
|
||||
VF610_PAD_PTE18 = 123,
|
||||
VF610_PAD_PTE19 = 124,
|
||||
VF610_PAD_PTE20 = 125,
|
||||
VF610_PAD_PTE21 = 126,
|
||||
VF610_PAD_PTE22 = 127,
|
||||
VF610_PAD_PTE23 = 128,
|
||||
VF610_PAD_PTE24 = 129,
|
||||
VF610_PAD_PTE25 = 130,
|
||||
VF610_PAD_PTE26 = 131,
|
||||
VF610_PAD_PTE27 = 132,
|
||||
VF610_PAD_PTE28 = 133,
|
||||
VF610_PAD_PTA7 = 134,
|
||||
};
|
||||
|
||||
/* Pad names for the pinmux subsystem */
|
||||
static const struct pinctrl_pin_desc vf610_pinctrl_pads[] = {
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA6),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA8),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA9),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA10),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA11),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA12),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA16),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA17),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA18),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA19),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA20),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA21),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA22),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA23),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA24),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA25),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA26),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA27),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA28),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA29),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA30),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA31),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB0),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB1),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB2),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB3),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB4),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB5),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB6),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB7),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB8),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB9),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB10),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB11),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB12),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB13),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB14),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB15),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB16),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB17),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB18),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB19),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB20),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB21),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB22),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC0),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC1),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC2),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC3),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC4),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC5),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC6),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC7),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC8),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC9),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC10),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC11),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC12),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC13),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC14),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC15),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC16),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC17),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD31),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD30),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD29),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD28),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD27),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD26),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD25),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD24),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD23),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD22),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD21),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD20),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD19),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD18),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD17),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD16),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD0),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD1),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD2),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD3),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD4),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD5),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD6),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD7),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD8),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD9),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD10),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD11),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD12),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTD13),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB23),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB24),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB25),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB26),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB27),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTB28),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC26),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC27),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC28),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC29),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC30),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTC31),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE0),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE1),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE2),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE3),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE4),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE5),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE6),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE7),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE8),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE9),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE10),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE11),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE12),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE13),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE14),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE15),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE16),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE17),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE18),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE19),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE20),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE21),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE22),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE23),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE24),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE25),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE26),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE27),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTE28),
|
||||
IMX_PINCTRL_PIN(VF610_PAD_PTA7),
|
||||
};
|
||||
|
||||
static struct imx_pinctrl_soc_info vf610_pinctrl_info = {
|
||||
.pins = vf610_pinctrl_pads,
|
||||
.npins = ARRAY_SIZE(vf610_pinctrl_pads),
|
||||
.flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG,
|
||||
};
|
||||
|
||||
static struct of_device_id vf610_pinctrl_of_match[] = {
|
||||
{ .compatible = "fsl,vf610-iomuxc", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int vf610_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
return imx_pinctrl_probe(pdev, &vf610_pinctrl_info);
|
||||
}
|
||||
|
||||
static struct platform_driver vf610_pinctrl_driver = {
|
||||
.driver = {
|
||||
.name = "vf610-pinctrl",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(vf610_pinctrl_of_match),
|
||||
},
|
||||
.probe = vf610_pinctrl_probe,
|
||||
.remove = imx_pinctrl_remove,
|
||||
};
|
||||
|
||||
static int __init vf610_pinctrl_init(void)
|
||||
{
|
||||
return platform_driver_register(&vf610_pinctrl_driver);
|
||||
}
|
||||
arch_initcall(vf610_pinctrl_init);
|
||||
|
||||
static void __exit vf610_pinctrl_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&vf610_pinctrl_driver);
|
||||
}
|
||||
module_exit(vf610_pinctrl_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Freescale VF610 pinctrl driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -18,6 +18,8 @@
|
|||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
@ -348,14 +350,72 @@ int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id sh_pfc_of_table[] = {
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A73A4
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a73a4",
|
||||
.data = &r8a73a4_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A7740
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a7740",
|
||||
.data = &r8a7740_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A7778
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a7778",
|
||||
.data = &r8a7778_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A7779
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a7779",
|
||||
.data = &r8a7779_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A7790
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a7790",
|
||||
.data = &r8a7790_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_SH7372
|
||||
{
|
||||
.compatible = "renesas,pfc-sh7372",
|
||||
.data = &sh7372_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_SH73A0
|
||||
{
|
||||
.compatible = "renesas,pfc-sh73a0",
|
||||
.data = &sh73a0_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sh_pfc_of_table);
|
||||
#endif
|
||||
|
||||
static int sh_pfc_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct platform_device_id *platid = platform_get_device_id(pdev);
|
||||
#ifdef CONFIG_OF
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
#endif
|
||||
const struct sh_pfc_soc_info *info;
|
||||
struct sh_pfc *pfc;
|
||||
int ret;
|
||||
|
||||
info = pdev->id_entry->driver_data
|
||||
? (void *)pdev->id_entry->driver_data : pdev->dev.platform_data;
|
||||
#ifdef CONFIG_OF
|
||||
if (np)
|
||||
info = of_match_device(sh_pfc_of_table, &pdev->dev)->data;
|
||||
else
|
||||
#endif
|
||||
info = platid ? (const void *)platid->driver_data : NULL;
|
||||
|
||||
if (info == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -501,6 +561,7 @@ static struct platform_driver sh_pfc_driver = {
|
|||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(sh_pfc_of_table),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
|
@ -72,11 +74,214 @@ static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
|||
seq_printf(s, "%s", DRV_NAME);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int sh_pfc_map_add_config(struct pinctrl_map *map,
|
||||
const char *group_or_pin,
|
||||
enum pinctrl_map_type type,
|
||||
unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
unsigned long *cfgs;
|
||||
|
||||
cfgs = kmemdup(configs, num_configs * sizeof(*cfgs),
|
||||
GFP_KERNEL);
|
||||
if (cfgs == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
map->type = type;
|
||||
map->data.configs.group_or_pin = group_or_pin;
|
||||
map->data.configs.configs = cfgs;
|
||||
map->data.configs.num_configs = num_configs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_pfc_dt_subnode_to_map(struct device *dev, struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned int *num_maps, unsigned int *index)
|
||||
{
|
||||
struct pinctrl_map *maps = *map;
|
||||
unsigned int nmaps = *num_maps;
|
||||
unsigned int idx = *index;
|
||||
unsigned int num_configs;
|
||||
const char *function = NULL;
|
||||
unsigned long *configs;
|
||||
struct property *prop;
|
||||
unsigned int num_groups;
|
||||
unsigned int num_pins;
|
||||
const char *group;
|
||||
const char *pin;
|
||||
int ret;
|
||||
|
||||
/* Parse the function and configuration properties. At least a function
|
||||
* or one configuration must be specified.
|
||||
*/
|
||||
ret = of_property_read_string(np, "renesas,function", &function);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
dev_err(dev, "Invalid function in DT\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pinconf_generic_parse_dt_config(np, &configs, &num_configs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!function && num_configs == 0) {
|
||||
dev_err(dev,
|
||||
"DT node must contain at least a function or config\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Count the number of pins and groups and reallocate mappings. */
|
||||
ret = of_property_count_strings(np, "renesas,pins");
|
||||
if (ret == -EINVAL) {
|
||||
num_pins = 0;
|
||||
} else if (ret < 0) {
|
||||
dev_err(dev, "Invalid pins list in DT\n");
|
||||
goto done;
|
||||
} else {
|
||||
num_pins = ret;
|
||||
}
|
||||
|
||||
ret = of_property_count_strings(np, "renesas,groups");
|
||||
if (ret == -EINVAL) {
|
||||
num_groups = 0;
|
||||
} else if (ret < 0) {
|
||||
dev_err(dev, "Invalid pin groups list in DT\n");
|
||||
goto done;
|
||||
} else {
|
||||
num_groups = ret;
|
||||
}
|
||||
|
||||
if (!num_pins && !num_groups) {
|
||||
dev_err(dev, "No pin or group provided in DT node\n");
|
||||
ret = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (function)
|
||||
nmaps += num_groups;
|
||||
if (configs)
|
||||
nmaps += num_pins + num_groups;
|
||||
|
||||
maps = krealloc(maps, sizeof(*maps) * nmaps, GFP_KERNEL);
|
||||
if (maps == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*map = maps;
|
||||
*num_maps = nmaps;
|
||||
|
||||
/* Iterate over pins and groups and create the mappings. */
|
||||
of_property_for_each_string(np, "renesas,groups", prop, group) {
|
||||
if (function) {
|
||||
maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
maps[idx].data.mux.group = group;
|
||||
maps[idx].data.mux.function = function;
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (configs) {
|
||||
ret = sh_pfc_map_add_config(&maps[idx], group,
|
||||
PIN_MAP_TYPE_CONFIGS_GROUP,
|
||||
configs, num_configs);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!configs) {
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
of_property_for_each_string(np, "renesas,pins", prop, pin) {
|
||||
ret = sh_pfc_map_add_config(&maps[idx], pin,
|
||||
PIN_MAP_TYPE_CONFIGS_PIN,
|
||||
configs, num_configs);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
done:
|
||||
*index = idx;
|
||||
kfree(configs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sh_pfc_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map, unsigned num_maps)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (map == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_maps; ++i) {
|
||||
if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP ||
|
||||
map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
|
||||
kfree(map[i].data.configs.configs);
|
||||
}
|
||||
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static int sh_pfc_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map, unsigned *num_maps)
|
||||
{
|
||||
struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct device *dev = pmx->pfc->dev;
|
||||
struct device_node *child;
|
||||
unsigned int index;
|
||||
int ret;
|
||||
|
||||
*map = NULL;
|
||||
*num_maps = 0;
|
||||
index = 0;
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
ret = sh_pfc_dt_subnode_to_map(dev, child, map, num_maps,
|
||||
&index);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* If no mapping has been found in child nodes try the config node. */
|
||||
if (*num_maps == 0) {
|
||||
ret = sh_pfc_dt_subnode_to_map(dev, np, map, num_maps, &index);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (*num_maps)
|
||||
return 0;
|
||||
|
||||
dev_err(dev, "no mapping found in node %s\n", np->full_name);
|
||||
ret = -EINVAL;
|
||||
|
||||
done:
|
||||
if (ret < 0)
|
||||
sh_pfc_dt_free_map(pctldev, *map, *num_maps);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static const struct pinctrl_ops sh_pfc_pinctrl_ops = {
|
||||
.get_groups_count = sh_pfc_get_groups_count,
|
||||
.get_group_name = sh_pfc_get_group_name,
|
||||
.get_group_pins = sh_pfc_get_group_pins,
|
||||
.pin_dbg_show = sh_pfc_pin_dbg_show,
|
||||
#ifdef CONFIG_OF
|
||||
.dt_node_to_map = sh_pfc_dt_node_to_map,
|
||||
.dt_free_map = sh_pfc_dt_free_map,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev)
|
||||
|
|
|
|||
5
drivers/pinctrl/sirf/Makefile
Normal file
5
drivers/pinctrl/sirf/Makefile
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# CSR SiRFsoc pinmux support
|
||||
|
||||
obj-y += pinctrl-sirf.o
|
||||
obj-y += pinctrl-prima2.o
|
||||
obj-y += pinctrl-atlas6.o
|
||||
947
drivers/pinctrl/sirf/pinctrl-atlas6.c
Normal file
947
drivers/pinctrl/sirf/pinctrl-atlas6.c
Normal file
|
|
@ -0,0 +1,947 @@
|
|||
/*
|
||||
* pinctrl pads, groups, functions for CSR SiRFatlasVI
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include "pinctrl-sirf.h"
|
||||
|
||||
/*
|
||||
* pad list for the pinmux subsystem
|
||||
* refer to atlasVI_io_table_v0.93.xls
|
||||
*/
|
||||
static const struct pinctrl_pin_desc sirfsoc_pads[] = {
|
||||
PINCTRL_PIN(0, "gpio0-0"),
|
||||
PINCTRL_PIN(1, "gpio0-1"),
|
||||
PINCTRL_PIN(2, "gpio0-2"),
|
||||
PINCTRL_PIN(3, "gpio0-3"),
|
||||
PINCTRL_PIN(4, "pwm0"),
|
||||
PINCTRL_PIN(5, "pwm1"),
|
||||
PINCTRL_PIN(6, "pwm2"),
|
||||
PINCTRL_PIN(7, "pwm3"),
|
||||
PINCTRL_PIN(8, "warm_rst_b"),
|
||||
PINCTRL_PIN(9, "odo_0"),
|
||||
PINCTRL_PIN(10, "odo_1"),
|
||||
PINCTRL_PIN(11, "dr_dir"),
|
||||
PINCTRL_PIN(12, "rts_0"),
|
||||
PINCTRL_PIN(13, "scl_1"),
|
||||
PINCTRL_PIN(14, "ntrst"),
|
||||
PINCTRL_PIN(15, "sda_1"),
|
||||
PINCTRL_PIN(16, "x_ldd[16]"),
|
||||
PINCTRL_PIN(17, "x_ldd[17]"),
|
||||
PINCTRL_PIN(18, "x_ldd[18]"),
|
||||
PINCTRL_PIN(19, "x_ldd[19]"),
|
||||
PINCTRL_PIN(20, "x_ldd[20]"),
|
||||
PINCTRL_PIN(21, "x_ldd[21]"),
|
||||
PINCTRL_PIN(22, "x_ldd[22]"),
|
||||
PINCTRL_PIN(23, "x_ldd[23]"),
|
||||
PINCTRL_PIN(24, "gps_sgn"),
|
||||
PINCTRL_PIN(25, "gps_mag"),
|
||||
PINCTRL_PIN(26, "gps_clk"),
|
||||
PINCTRL_PIN(27, "sd_cd_b_2"),
|
||||
PINCTRL_PIN(28, "sd_vcc_on_2"),
|
||||
PINCTRL_PIN(29, "sd_wp_b_2"),
|
||||
PINCTRL_PIN(30, "sd_clk_3"),
|
||||
PINCTRL_PIN(31, "sd_cmd_3"),
|
||||
|
||||
PINCTRL_PIN(32, "x_sd_dat_3[0]"),
|
||||
PINCTRL_PIN(33, "x_sd_dat_3[1]"),
|
||||
PINCTRL_PIN(34, "x_sd_dat_3[2]"),
|
||||
PINCTRL_PIN(35, "x_sd_dat_3[3]"),
|
||||
PINCTRL_PIN(36, "usb_clk"),
|
||||
PINCTRL_PIN(37, "usb_dir"),
|
||||
PINCTRL_PIN(38, "usb_nxt"),
|
||||
PINCTRL_PIN(39, "usb_stp"),
|
||||
PINCTRL_PIN(40, "usb_dat[7]"),
|
||||
PINCTRL_PIN(41, "usb_dat[6]"),
|
||||
PINCTRL_PIN(42, "x_cko_1"),
|
||||
PINCTRL_PIN(43, "spi_clk_1"),
|
||||
PINCTRL_PIN(44, "spi_dout_1"),
|
||||
PINCTRL_PIN(45, "spi_din_1"),
|
||||
PINCTRL_PIN(46, "spi_en_1"),
|
||||
PINCTRL_PIN(47, "x_txd_1"),
|
||||
PINCTRL_PIN(48, "x_txd_2"),
|
||||
PINCTRL_PIN(49, "x_rxd_1"),
|
||||
PINCTRL_PIN(50, "x_rxd_2"),
|
||||
PINCTRL_PIN(51, "x_usclk_0"),
|
||||
PINCTRL_PIN(52, "x_utxd_0"),
|
||||
PINCTRL_PIN(53, "x_urxd_0"),
|
||||
PINCTRL_PIN(54, "x_utfs_0"),
|
||||
PINCTRL_PIN(55, "x_urfs_0"),
|
||||
PINCTRL_PIN(56, "usb_dat5"),
|
||||
PINCTRL_PIN(57, "usb_dat4"),
|
||||
PINCTRL_PIN(58, "usb_dat3"),
|
||||
PINCTRL_PIN(59, "usb_dat2"),
|
||||
PINCTRL_PIN(60, "usb_dat1"),
|
||||
PINCTRL_PIN(61, "usb_dat0"),
|
||||
PINCTRL_PIN(62, "x_ldd[14]"),
|
||||
PINCTRL_PIN(63, "x_ldd[15]"),
|
||||
|
||||
PINCTRL_PIN(64, "x_gps_gpio"),
|
||||
PINCTRL_PIN(65, "x_ldd[13]"),
|
||||
PINCTRL_PIN(66, "x_df_we_b"),
|
||||
PINCTRL_PIN(67, "x_df_re_b"),
|
||||
PINCTRL_PIN(68, "x_txd_0"),
|
||||
PINCTRL_PIN(69, "x_rxd_0"),
|
||||
PINCTRL_PIN(70, "x_l_lck"),
|
||||
PINCTRL_PIN(71, "x_l_fck"),
|
||||
PINCTRL_PIN(72, "x_l_de"),
|
||||
PINCTRL_PIN(73, "x_ldd[0]"),
|
||||
PINCTRL_PIN(74, "x_ldd[1]"),
|
||||
PINCTRL_PIN(75, "x_ldd[2]"),
|
||||
PINCTRL_PIN(76, "x_ldd[3]"),
|
||||
PINCTRL_PIN(77, "x_ldd[4]"),
|
||||
PINCTRL_PIN(78, "x_cko_0"),
|
||||
PINCTRL_PIN(79, "x_ldd[5]"),
|
||||
PINCTRL_PIN(80, "x_ldd[6]"),
|
||||
PINCTRL_PIN(81, "x_ldd[7]"),
|
||||
PINCTRL_PIN(82, "x_ldd[8]"),
|
||||
PINCTRL_PIN(83, "x_ldd[9]"),
|
||||
PINCTRL_PIN(84, "x_ldd[10]"),
|
||||
PINCTRL_PIN(85, "x_ldd[11]"),
|
||||
PINCTRL_PIN(86, "x_ldd[12]"),
|
||||
PINCTRL_PIN(87, "x_vip_vsync"),
|
||||
PINCTRL_PIN(88, "x_vip_hsync"),
|
||||
PINCTRL_PIN(89, "x_vip_pxclk"),
|
||||
PINCTRL_PIN(90, "x_sda_0"),
|
||||
PINCTRL_PIN(91, "x_scl_0"),
|
||||
PINCTRL_PIN(92, "x_df_ry_by"),
|
||||
PINCTRL_PIN(93, "x_df_cs_b[1]"),
|
||||
PINCTRL_PIN(94, "x_df_cs_b[0]"),
|
||||
PINCTRL_PIN(95, "x_l_pclk"),
|
||||
|
||||
PINCTRL_PIN(96, "x_df_dqs"),
|
||||
PINCTRL_PIN(97, "x_df_wp_b"),
|
||||
PINCTRL_PIN(98, "ac97_sync"),
|
||||
PINCTRL_PIN(99, "ac97_bit_clk "),
|
||||
PINCTRL_PIN(100, "ac97_dout"),
|
||||
PINCTRL_PIN(101, "ac97_din"),
|
||||
PINCTRL_PIN(102, "x_rtc_io"),
|
||||
};
|
||||
|
||||
static const struct sirfsoc_muxmask lcd_16bits_sirfsoc_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(30) | BIT(31),
|
||||
}, {
|
||||
.group = 2,
|
||||
.mask = BIT(1) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) |
|
||||
BIT(12) | BIT(13) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) |
|
||||
BIT(20) | BIT(21) | BIT(22) | BIT(31),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux lcd_16bits_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(lcd_16bits_sirfsoc_muxmask),
|
||||
.muxmask = lcd_16bits_sirfsoc_muxmask,
|
||||
.funcmask = BIT(4),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned lcd_16bits_pins[] = { 62, 63, 65, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83,
|
||||
84, 85, 86, 95 };
|
||||
|
||||
static const struct sirfsoc_muxmask lcd_18bits_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(1) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) |
|
||||
BIT(12) | BIT(13) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) |
|
||||
BIT(20) | BIT(21) | BIT(22) | BIT(31),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(30) | BIT(31),
|
||||
}, {
|
||||
.group = 0,
|
||||
.mask = BIT(16) | BIT(17),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux lcd_18bits_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(lcd_18bits_muxmask),
|
||||
.muxmask = lcd_18bits_muxmask,
|
||||
.funcmask = BIT(4) | BIT(15),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned lcd_18bits_pins[] = { 16, 17, 62, 63, 65, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83,
|
||||
84, 85, 86, 95 };
|
||||
|
||||
static const struct sirfsoc_muxmask lcd_24bits_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(1) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) |
|
||||
BIT(12) | BIT(13) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) |
|
||||
BIT(20) | BIT(21) | BIT(22) | BIT(31),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(30) | BIT(31),
|
||||
}, {
|
||||
.group = 0,
|
||||
.mask = BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux lcd_24bits_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(lcd_24bits_muxmask),
|
||||
.muxmask = lcd_24bits_muxmask,
|
||||
.funcmask = BIT(4) | BIT(15),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned lcd_24bits_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, 62, 63, 65, 70, 71, 72, 73, 74, 75, 76, 77, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 95};
|
||||
|
||||
static const struct sirfsoc_muxmask lcdrom_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(1) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) |
|
||||
BIT(12) | BIT(13) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) |
|
||||
BIT(20) | BIT(21) | BIT(22) | BIT(31),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(30) | BIT(31),
|
||||
}, {
|
||||
.group = 0,
|
||||
.mask = BIT(8),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux lcdrom_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(lcdrom_muxmask),
|
||||
.muxmask = lcdrom_muxmask,
|
||||
.funcmask = BIT(4),
|
||||
.funcval = BIT(4),
|
||||
};
|
||||
|
||||
static const unsigned lcdrom_pins[] = { 8, 62, 63, 65, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83,
|
||||
84, 85, 86, 95};
|
||||
|
||||
static const struct sirfsoc_muxmask uart0_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(12),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(23),
|
||||
}, {
|
||||
.group = 2,
|
||||
.mask = BIT(4) | BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux uart0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(uart0_muxmask),
|
||||
.muxmask = uart0_muxmask,
|
||||
.funcmask = BIT(9),
|
||||
.funcval = BIT(9),
|
||||
};
|
||||
|
||||
static const unsigned uart0_pins[] = { 12, 55, 68, 69 };
|
||||
|
||||
static const struct sirfsoc_muxmask uart0_nostreamctrl_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(4) | BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux uart0_nostreamctrl_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(uart0_nostreamctrl_muxmask),
|
||||
.muxmask = uart0_nostreamctrl_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned uart0_nostreamctrl_pins[] = { 68, 69 };
|
||||
|
||||
static const struct sirfsoc_muxmask uart1_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(15) | BIT(17),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux uart1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(uart1_muxmask),
|
||||
.muxmask = uart1_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned uart1_pins[] = { 47, 49 };
|
||||
|
||||
static const struct sirfsoc_muxmask uart2_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(10) | BIT(14),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(16) | BIT(18),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux uart2_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(uart2_muxmask),
|
||||
.muxmask = uart2_muxmask,
|
||||
.funcmask = BIT(10),
|
||||
.funcval = BIT(10),
|
||||
};
|
||||
|
||||
static const unsigned uart2_pins[] = { 10, 14, 48, 50 };
|
||||
|
||||
static const struct sirfsoc_muxmask uart2_nostreamctrl_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(16) | BIT(18),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux uart2_nostreamctrl_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(uart2_nostreamctrl_muxmask),
|
||||
.muxmask = uart2_nostreamctrl_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned uart2_nostreamctrl_pins[] = { 48, 50 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc3_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(30) | BIT(31),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(0) | BIT(1) | BIT(2) | BIT(3),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc3_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc3_muxmask),
|
||||
.muxmask = sdmmc3_muxmask,
|
||||
.funcmask = BIT(7),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned sdmmc3_pins[] = { 30, 31, 32, 33, 34, 35 };
|
||||
|
||||
static const struct sirfsoc_muxmask spi0_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(30),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(0) | BIT(2) | BIT(3),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux spi0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(spi0_muxmask),
|
||||
.muxmask = spi0_muxmask,
|
||||
.funcmask = BIT(7),
|
||||
.funcval = BIT(7),
|
||||
};
|
||||
|
||||
static const unsigned spi0_pins[] = { 30, 32, 34, 35 };
|
||||
|
||||
static const struct sirfsoc_muxmask cko1_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(10),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux cko1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(cko1_muxmask),
|
||||
.muxmask = cko1_muxmask,
|
||||
.funcmask = BIT(3),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned cko1_pins[] = { 42 };
|
||||
|
||||
static const struct sirfsoc_muxmask i2s_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(10),
|
||||
}, {
|
||||
.group = 3,
|
||||
.mask = BIT(2) | BIT(3) | BIT(4) | BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux i2s_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(i2s_muxmask),
|
||||
.muxmask = i2s_muxmask,
|
||||
.funcmask = BIT(3),
|
||||
.funcval = BIT(3),
|
||||
};
|
||||
|
||||
static const unsigned i2s_pins[] = { 42, 98, 99, 100, 101 };
|
||||
|
||||
static const struct sirfsoc_muxmask i2s_no_din_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(10),
|
||||
}, {
|
||||
.group = 3,
|
||||
.mask = BIT(2) | BIT(3) | BIT(4),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux i2s_no_din_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(i2s_no_din_muxmask),
|
||||
.muxmask = i2s_no_din_muxmask,
|
||||
.funcmask = BIT(3),
|
||||
.funcval = BIT(3),
|
||||
};
|
||||
|
||||
static const unsigned i2s_no_din_pins[] = { 42, 98, 99, 100 };
|
||||
|
||||
static const struct sirfsoc_muxmask i2s_6chn_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(10) | BIT(20) | BIT(23),
|
||||
}, {
|
||||
.group = 3,
|
||||
.mask = BIT(2) | BIT(3) | BIT(4) | BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux i2s_6chn_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(i2s_6chn_muxmask),
|
||||
.muxmask = i2s_6chn_muxmask,
|
||||
.funcmask = BIT(1) | BIT(3) | BIT(9),
|
||||
.funcval = BIT(1) | BIT(3) | BIT(9),
|
||||
};
|
||||
|
||||
static const unsigned i2s_6chn_pins[] = { 42, 52, 55, 98, 99, 100, 101 };
|
||||
|
||||
static const struct sirfsoc_muxmask ac97_muxmask[] = {
|
||||
{
|
||||
.group = 3,
|
||||
.mask = BIT(2) | BIT(3) | BIT(4) | BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux ac97_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(ac97_muxmask),
|
||||
.muxmask = ac97_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned ac97_pins[] = { 98, 99, 100, 101 };
|
||||
|
||||
static const struct sirfsoc_muxmask spi1_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(11) | BIT(12) | BIT(13) | BIT(14),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux spi1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(spi1_muxmask),
|
||||
.muxmask = spi1_muxmask,
|
||||
.funcmask = BIT(16),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned spi1_pins[] = { 43, 44, 45, 46 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc1_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(2) | BIT(3),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc1_muxmask),
|
||||
.muxmask = sdmmc1_muxmask,
|
||||
.funcmask = BIT(5),
|
||||
.funcval = BIT(5),
|
||||
};
|
||||
|
||||
static const unsigned sdmmc1_pins[] = { 66, 67 };
|
||||
|
||||
static const struct sirfsoc_muxmask gps_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(24) | BIT(25) | BIT(26),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux gps_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(gps_muxmask),
|
||||
.muxmask = gps_muxmask,
|
||||
.funcmask = BIT(13),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned gps_pins[] = { 24, 25, 26 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc5_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(24) | BIT(25) | BIT(26),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc5_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc5_muxmask),
|
||||
.muxmask = sdmmc5_muxmask,
|
||||
.funcmask = BIT(13),
|
||||
.funcval = BIT(13),
|
||||
};
|
||||
|
||||
static const unsigned sdmmc5_pins[] = { 24, 25, 26 };
|
||||
|
||||
static const struct sirfsoc_muxmask usp0_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(19) | BIT(20) | BIT(21) | BIT(22),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux usp0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(usp0_muxmask),
|
||||
.muxmask = usp0_muxmask,
|
||||
.funcmask = BIT(1) | BIT(2) | BIT(9),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned usp0_pins[] = { 51, 52, 53, 54 };
|
||||
|
||||
static const struct sirfsoc_muxmask usp1_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(15),
|
||||
}, {
|
||||
.group = 1,
|
||||
.mask = BIT(11) | BIT(12) | BIT(13) | BIT(14),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux usp1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(usp1_muxmask),
|
||||
.muxmask = usp1_muxmask,
|
||||
.funcmask = BIT(16),
|
||||
.funcval = BIT(16),
|
||||
};
|
||||
|
||||
static const unsigned usp1_pins[] = { 15, 43, 44, 45, 46 };
|
||||
|
||||
static const struct sirfsoc_muxmask nand_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(2) | BIT(3) | BIT(28) | BIT(29) | BIT(30),
|
||||
}, {
|
||||
.group = 3,
|
||||
.mask = BIT(0) | BIT(1),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux nand_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(nand_muxmask),
|
||||
.muxmask = nand_muxmask,
|
||||
.funcmask = BIT(5) | BIT(19),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned nand_pins[] = { 66, 67, 92, 93, 94, 96, 97 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc0_muxmask[] = {
|
||||
{
|
||||
.group = 3,
|
||||
.mask = BIT(1),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc0_muxmask),
|
||||
.muxmask = sdmmc0_muxmask,
|
||||
.funcmask = BIT(5) | BIT(19),
|
||||
.funcval = BIT(19),
|
||||
};
|
||||
|
||||
static const unsigned sdmmc0_pins[] = { 97 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc2_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(27) | BIT(28) | BIT(29),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc2_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc2_muxmask),
|
||||
.muxmask = sdmmc2_muxmask,
|
||||
.funcmask = BIT(11),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned sdmmc2_pins[] = { 27, 28, 29 };
|
||||
|
||||
static const struct sirfsoc_muxmask sdmmc2_nowp_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(27) | BIT(28),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux sdmmc2_nowp_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(sdmmc2_nowp_muxmask),
|
||||
.muxmask = sdmmc2_nowp_muxmask,
|
||||
.funcmask = BIT(11),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned sdmmc2_nowp_pins[] = { 27, 28 };
|
||||
|
||||
static const struct sirfsoc_muxmask cko0_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(14),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux cko0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(cko0_muxmask),
|
||||
.muxmask = cko0_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned cko0_pins[] = { 78 };
|
||||
|
||||
static const struct sirfsoc_muxmask vip_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(4) | BIT(5) | BIT(6) | BIT(8) | BIT(9)
|
||||
| BIT(24) | BIT(25) | BIT(26) | BIT(27) | BIT(28) |
|
||||
BIT(29),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux vip_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(vip_muxmask),
|
||||
.muxmask = vip_muxmask,
|
||||
.funcmask = BIT(18),
|
||||
.funcval = BIT(18),
|
||||
};
|
||||
|
||||
static const unsigned vip_pins[] = { 36, 37, 38, 40, 41, 56, 57, 58, 59, 60, 61 };
|
||||
|
||||
static const struct sirfsoc_muxmask vip_noupli_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20)
|
||||
| BIT(21) | BIT(22) | BIT(23),
|
||||
}, {
|
||||
.group = 2,
|
||||
.mask = BIT(23) | BIT(24) | BIT(25),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux vip_noupli_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(vip_noupli_muxmask),
|
||||
.muxmask = vip_noupli_muxmask,
|
||||
.funcmask = BIT(15),
|
||||
.funcval = BIT(15),
|
||||
};
|
||||
|
||||
static const unsigned vip_noupli_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, 87, 88, 89 };
|
||||
|
||||
static const struct sirfsoc_muxmask i2c0_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(26) | BIT(27),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux i2c0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(i2c0_muxmask),
|
||||
.muxmask = i2c0_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned i2c0_pins[] = { 90, 91 };
|
||||
|
||||
static const struct sirfsoc_muxmask i2c1_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(13) | BIT(15),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux i2c1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(i2c1_muxmask),
|
||||
.muxmask = i2c1_muxmask,
|
||||
.funcmask = BIT(16),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned i2c1_pins[] = { 13, 15 };
|
||||
|
||||
static const struct sirfsoc_muxmask pwm0_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(4),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pwm0_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pwm0_muxmask),
|
||||
.muxmask = pwm0_muxmask,
|
||||
.funcmask = BIT(12),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned pwm0_pins[] = { 4 };
|
||||
|
||||
static const struct sirfsoc_muxmask pwm1_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(5),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pwm1_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pwm1_muxmask),
|
||||
.muxmask = pwm1_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned pwm1_pins[] = { 5 };
|
||||
|
||||
static const struct sirfsoc_muxmask pwm2_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(6),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pwm2_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pwm2_muxmask),
|
||||
.muxmask = pwm2_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned pwm2_pins[] = { 6 };
|
||||
|
||||
static const struct sirfsoc_muxmask pwm3_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(7),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pwm3_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pwm3_muxmask),
|
||||
.muxmask = pwm3_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned pwm3_pins[] = { 7 };
|
||||
|
||||
static const struct sirfsoc_muxmask pwm4_muxmask[] = {
|
||||
{
|
||||
.group = 2,
|
||||
.mask = BIT(14),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pwm4_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pwm4_muxmask),
|
||||
.muxmask = pwm4_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned pwm4_pins[] = { 78 };
|
||||
|
||||
static const struct sirfsoc_muxmask warm_rst_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(8),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux warm_rst_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(warm_rst_muxmask),
|
||||
.muxmask = warm_rst_muxmask,
|
||||
.funcmask = BIT(4),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned warm_rst_pins[] = { 8 };
|
||||
|
||||
static const struct sirfsoc_muxmask usb0_upli_drvbus_muxmask[] = {
|
||||
{
|
||||
.group = 1,
|
||||
.mask = BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8)
|
||||
| BIT(9) | BIT(24) | BIT(25) | BIT(26) |
|
||||
BIT(27) | BIT(28) | BIT(29),
|
||||
},
|
||||
};
|
||||
static const struct sirfsoc_padmux usb0_upli_drvbus_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(usb0_upli_drvbus_muxmask),
|
||||
.muxmask = usb0_upli_drvbus_muxmask,
|
||||
.funcmask = BIT(18),
|
||||
.funcval = 0,
|
||||
};
|
||||
|
||||
static const unsigned usb0_upli_drvbus_pins[] = { 36, 37, 38, 39, 40, 41, 56, 57, 58, 59, 60, 61 };
|
||||
|
||||
static const struct sirfsoc_muxmask usb1_utmi_drvbus_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(28),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux usb1_utmi_drvbus_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(usb1_utmi_drvbus_muxmask),
|
||||
.muxmask = usb1_utmi_drvbus_muxmask,
|
||||
.funcmask = BIT(11),
|
||||
.funcval = BIT(11), /* refer to PAD_UTMI_DRVVBUS1_ENABLE */
|
||||
};
|
||||
|
||||
static const unsigned usb1_utmi_drvbus_pins[] = { 28 };
|
||||
|
||||
static const struct sirfsoc_muxmask pulse_count_muxmask[] = {
|
||||
{
|
||||
.group = 0,
|
||||
.mask = BIT(9) | BIT(10) | BIT(11),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct sirfsoc_padmux pulse_count_padmux = {
|
||||
.muxmask_counts = ARRAY_SIZE(pulse_count_muxmask),
|
||||
.muxmask = pulse_count_muxmask,
|
||||
};
|
||||
|
||||
static const unsigned pulse_count_pins[] = { 9, 10, 11 };
|
||||
|
||||
static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = {
|
||||
SIRFSOC_PIN_GROUP("lcd_16bitsgrp", lcd_16bits_pins),
|
||||
SIRFSOC_PIN_GROUP("lcd_18bitsgrp", lcd_18bits_pins),
|
||||
SIRFSOC_PIN_GROUP("lcd_24bitsgrp", lcd_24bits_pins),
|
||||
SIRFSOC_PIN_GROUP("lcdrom_grp", lcdrom_pins),
|
||||
SIRFSOC_PIN_GROUP("uart0grp", uart0_pins),
|
||||
SIRFSOC_PIN_GROUP("uart1grp", uart1_pins),
|
||||
SIRFSOC_PIN_GROUP("uart2grp", uart2_pins),
|
||||
SIRFSOC_PIN_GROUP("uart2_nostreamctrlgrp", uart2_nostreamctrl_pins),
|
||||
SIRFSOC_PIN_GROUP("usp0grp", usp0_pins),
|
||||
SIRFSOC_PIN_GROUP("usp1grp", usp1_pins),
|
||||
SIRFSOC_PIN_GROUP("i2c0grp", i2c0_pins),
|
||||
SIRFSOC_PIN_GROUP("i2c1grp", i2c1_pins),
|
||||
SIRFSOC_PIN_GROUP("pwm0grp", pwm0_pins),
|
||||
SIRFSOC_PIN_GROUP("pwm1grp", pwm1_pins),
|
||||
SIRFSOC_PIN_GROUP("pwm2grp", pwm2_pins),
|
||||
SIRFSOC_PIN_GROUP("pwm3grp", pwm3_pins),
|
||||
SIRFSOC_PIN_GROUP("pwm4grp", pwm4_pins),
|
||||
SIRFSOC_PIN_GROUP("vipgrp", vip_pins),
|
||||
SIRFSOC_PIN_GROUP("vip_noupligrp", vip_noupli_pins),
|
||||
SIRFSOC_PIN_GROUP("warm_rstgrp", warm_rst_pins),
|
||||
SIRFSOC_PIN_GROUP("cko0grp", cko0_pins),
|
||||
SIRFSOC_PIN_GROUP("cko1grp", cko1_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc0grp", sdmmc0_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc1grp", sdmmc1_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc2grp", sdmmc2_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc2_nowpgrp", sdmmc2_nowp_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc3grp", sdmmc3_pins),
|
||||
SIRFSOC_PIN_GROUP("sdmmc5grp", sdmmc5_pins),
|
||||
SIRFSOC_PIN_GROUP("usb0_upli_drvbusgrp", usb0_upli_drvbus_pins),
|
||||
SIRFSOC_PIN_GROUP("usb1_utmi_drvbusgrp", usb1_utmi_drvbus_pins),
|
||||
SIRFSOC_PIN_GROUP("pulse_countgrp", pulse_count_pins),
|
||||
SIRFSOC_PIN_GROUP("i2sgrp", i2s_pins),
|
||||
SIRFSOC_PIN_GROUP("i2s_no_dingrp", i2s_no_din_pins),
|
||||
SIRFSOC_PIN_GROUP("i2s_6chngrp", i2s_6chn_pins),
|
||||
SIRFSOC_PIN_GROUP("ac97grp", ac97_pins),
|
||||
SIRFSOC_PIN_GROUP("nandgrp", nand_pins),
|
||||
SIRFSOC_PIN_GROUP("spi0grp", spi0_pins),
|
||||
SIRFSOC_PIN_GROUP("spi1grp", spi1_pins),
|
||||
SIRFSOC_PIN_GROUP("gpsgrp", gps_pins),
|
||||
};
|
||||
|
||||
static const char * const lcd_16bitsgrp[] = { "lcd_16bitsgrp" };
|
||||
static const char * const lcd_18bitsgrp[] = { "lcd_18bitsgrp" };
|
||||
static const char * const lcd_24bitsgrp[] = { "lcd_24bitsgrp" };
|
||||
static const char * const lcdromgrp[] = { "lcdromgrp" };
|
||||
static const char * const uart0grp[] = { "uart0grp" };
|
||||
static const char * const uart1grp[] = { "uart1grp" };
|
||||
static const char * const uart2grp[] = { "uart2grp" };
|
||||
static const char * const uart2_nostreamctrlgrp[] = { "uart2_nostreamctrlgrp" };
|
||||
static const char * const usp0grp[] = { "usp0grp" };
|
||||
static const char * const usp1grp[] = { "usp1grp" };
|
||||
static const char * const i2c0grp[] = { "i2c0grp" };
|
||||
static const char * const i2c1grp[] = { "i2c1grp" };
|
||||
static const char * const pwm0grp[] = { "pwm0grp" };
|
||||
static const char * const pwm1grp[] = { "pwm1grp" };
|
||||
static const char * const pwm2grp[] = { "pwm2grp" };
|
||||
static const char * const pwm3grp[] = { "pwm3grp" };
|
||||
static const char * const pwm4grp[] = { "pwm4grp" };
|
||||
static const char * const vipgrp[] = { "vipgrp" };
|
||||
static const char * const vip_noupligrp[] = { "vip_noupligrp" };
|
||||
static const char * const warm_rstgrp[] = { "warm_rstgrp" };
|
||||
static const char * const cko0grp[] = { "cko0grp" };
|
||||
static const char * const cko1grp[] = { "cko1grp" };
|
||||
static const char * const sdmmc0grp[] = { "sdmmc0grp" };
|
||||
static const char * const sdmmc1grp[] = { "sdmmc1grp" };
|
||||
static const char * const sdmmc2grp[] = { "sdmmc2grp" };
|
||||
static const char * const sdmmc3grp[] = { "sdmmc3grp" };
|
||||
static const char * const sdmmc5grp[] = { "sdmmc5grp" };
|
||||
static const char * const sdmmc2_nowpgrp[] = { "sdmmc2_nowpgrp" };
|
||||
static const char * const usb0_upli_drvbusgrp[] = { "usb0_upli_drvbusgrp" };
|
||||
static const char * const usb1_utmi_drvbusgrp[] = { "usb1_utmi_drvbusgrp" };
|
||||
static const char * const pulse_countgrp[] = { "pulse_countgrp" };
|
||||
static const char * const i2sgrp[] = { "i2sgrp" };
|
||||
static const char * const i2s_no_dingrp[] = { "i2s_no_dingrp" };
|
||||
static const char * const i2s_6chngrp[] = { "i2s_6chngrp" };
|
||||
static const char * const ac97grp[] = { "ac97grp" };
|
||||
static const char * const nandgrp[] = { "nandgrp" };
|
||||
static const char * const spi0grp[] = { "spi0grp" };
|
||||
static const char * const spi1grp[] = { "spi1grp" };
|
||||
static const char * const gpsgrp[] = { "gpsgrp" };
|
||||
|
||||
static const struct sirfsoc_pmx_func sirfsoc_pmx_functions[] = {
|
||||
SIRFSOC_PMX_FUNCTION("lcd_16bits", lcd_16bitsgrp, lcd_16bits_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("lcd_18bits", lcd_18bitsgrp, lcd_18bits_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("lcd_24bits", lcd_24bitsgrp, lcd_24bits_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("lcdrom", lcdromgrp, lcdrom_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("uart0", uart0grp, uart0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("uart1", uart1grp, uart1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("uart2", uart2grp, uart2_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("uart2_nostreamctrl", uart2_nostreamctrlgrp, uart2_nostreamctrl_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("usp0", usp0grp, usp0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("usp1", usp1grp, usp1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("i2c0", i2c0grp, i2c0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("i2c1", i2c1grp, i2c1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pwm0", pwm0grp, pwm0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pwm1", pwm1grp, pwm1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pwm2", pwm2grp, pwm2_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pwm3", pwm3grp, pwm3_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pwm4", pwm4grp, pwm4_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("vip", vipgrp, vip_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("vip_noupli", vip_noupligrp, vip_noupli_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("warm_rst", warm_rstgrp, warm_rst_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("cko0", cko0grp, cko0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("cko1", cko1grp, cko1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc0", sdmmc0grp, sdmmc0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc1", sdmmc1grp, sdmmc1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc2", sdmmc2grp, sdmmc2_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc3", sdmmc3grp, sdmmc3_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc5", sdmmc5grp, sdmmc5_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("sdmmc2_nowp", sdmmc2_nowpgrp, sdmmc2_nowp_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("usb0_upli_drvbus", usb0_upli_drvbusgrp, usb0_upli_drvbus_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("usb1_utmi_drvbus", usb1_utmi_drvbusgrp, usb1_utmi_drvbus_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("pulse_count", pulse_countgrp, pulse_count_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("i2s", i2sgrp, i2s_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("i2s_no_din", i2s_no_dingrp, i2s_no_din_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("i2s_6chn", i2s_6chngrp, i2s_6chn_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("ac97", ac97grp, ac97_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("nand", nandgrp, nand_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("spi0", spi0grp, spi0_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("spi1", spi1grp, spi1_padmux),
|
||||
SIRFSOC_PMX_FUNCTION("gps", gpsgrp, gps_padmux),
|
||||
};
|
||||
|
||||
struct sirfsoc_pinctrl_data atlas6_pinctrl_data = {
|
||||
(struct pinctrl_pin_desc *)sirfsoc_pads,
|
||||
ARRAY_SIZE(sirfsoc_pads),
|
||||
(struct sirfsoc_pin_group *)sirfsoc_pin_groups,
|
||||
ARRAY_SIZE(sirfsoc_pin_groups),
|
||||
(struct sirfsoc_pmx_func *)sirfsoc_pmx_functions,
|
||||
ARRAY_SIZE(sirfsoc_pmx_functions),
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load diff
929
drivers/pinctrl/sirf/pinctrl-sirf.c
Normal file
929
drivers/pinctrl/sirf/pinctrl-sirf.c
Normal file
|
|
@ -0,0 +1,929 @@
|
|||
/*
|
||||
* pinmux driver for CSR SiRFprimaII
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include "pinctrl-sirf.h"
|
||||
|
||||
#define DRIVER_NAME "pinmux-sirf"
|
||||
|
||||
struct sirfsoc_gpio_bank {
|
||||
struct of_mm_gpio_chip chip;
|
||||
struct irq_domain *domain;
|
||||
int id;
|
||||
int parent_irq;
|
||||
spinlock_t lock;
|
||||
bool is_marco; /* for marco, some registers are different with prima2 */
|
||||
};
|
||||
|
||||
static struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
static DEFINE_SPINLOCK(sgpio_lock);
|
||||
|
||||
static struct sirfsoc_pin_group *sirfsoc_pin_groups;
|
||||
static int sirfsoc_pingrp_cnt;
|
||||
|
||||
static int sirfsoc_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
return sirfsoc_pingrp_cnt;
|
||||
}
|
||||
|
||||
static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned selector)
|
||||
{
|
||||
return sirfsoc_pin_groups[selector].name;
|
||||
}
|
||||
|
||||
static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
const unsigned **pins,
|
||||
unsigned *num_pins)
|
||||
{
|
||||
*pins = sirfsoc_pin_groups[selector].pins;
|
||||
*num_pins = sirfsoc_pin_groups[selector].num_pins;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
||||
unsigned offset)
|
||||
{
|
||||
seq_printf(s, " " DRIVER_NAME);
|
||||
}
|
||||
|
||||
static int sirfsoc_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map, unsigned *num_maps)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct device_node *np;
|
||||
struct property *prop;
|
||||
const char *function, *group;
|
||||
int ret, index = 0, count = 0;
|
||||
|
||||
/* calculate number of maps required */
|
||||
for_each_child_of_node(np_config, np) {
|
||||
ret = of_property_read_string(np, "sirf,function", &function);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = of_property_count_strings(np, "sirf,pins");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
count += ret;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
dev_err(spmx->dev, "No child nodes passed via DT\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
*map = kzalloc(sizeof(**map) * count, GFP_KERNEL);
|
||||
if (!*map)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_child_of_node(np_config, np) {
|
||||
of_property_read_string(np, "sirf,function", &function);
|
||||
of_property_for_each_string(np, "sirf,pins", prop, group) {
|
||||
(*map)[index].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
(*map)[index].data.mux.group = group;
|
||||
(*map)[index].data.mux.function = function;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
*num_maps = count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map, unsigned num_maps)
|
||||
{
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static struct pinctrl_ops sirfsoc_pctrl_ops = {
|
||||
.get_groups_count = sirfsoc_get_groups_count,
|
||||
.get_group_name = sirfsoc_get_group_name,
|
||||
.get_group_pins = sirfsoc_get_group_pins,
|
||||
.pin_dbg_show = sirfsoc_pin_dbg_show,
|
||||
.dt_node_to_map = sirfsoc_dt_node_to_map,
|
||||
.dt_free_map = sirfsoc_dt_free_map,
|
||||
};
|
||||
|
||||
static struct sirfsoc_pmx_func *sirfsoc_pmx_functions;
|
||||
static int sirfsoc_pmxfunc_cnt;
|
||||
|
||||
static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector,
|
||||
bool enable)
|
||||
{
|
||||
int i;
|
||||
const struct sirfsoc_padmux *mux = sirfsoc_pmx_functions[selector].padmux;
|
||||
const struct sirfsoc_muxmask *mask = mux->muxmask;
|
||||
|
||||
for (i = 0; i < mux->muxmask_counts; i++) {
|
||||
u32 muxval;
|
||||
if (!spmx->is_marco) {
|
||||
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
|
||||
if (enable)
|
||||
muxval = muxval & ~mask[i].mask;
|
||||
else
|
||||
muxval = muxval | mask[i].mask;
|
||||
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
|
||||
} else {
|
||||
if (enable)
|
||||
writel(mask[i].mask, spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN_CLR(mask[i].group));
|
||||
else
|
||||
writel(mask[i].mask, spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(mask[i].group));
|
||||
}
|
||||
}
|
||||
|
||||
if (mux->funcmask && enable) {
|
||||
u32 func_en_val;
|
||||
func_en_val =
|
||||
readl(spmx->rsc_virtbase + SIRFSOC_RSC_PIN_MUX);
|
||||
func_en_val =
|
||||
(func_en_val & ~mux->funcmask) | (mux->
|
||||
funcval);
|
||||
writel(func_en_val, spmx->rsc_virtbase + SIRFSOC_RSC_PIN_MUX);
|
||||
}
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_enable(struct pinctrl_dev *pmxdev, unsigned selector,
|
||||
unsigned group)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx;
|
||||
|
||||
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
||||
sirfsoc_pinmux_endisable(spmx, selector, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_pinmux_disable(struct pinctrl_dev *pmxdev, unsigned selector,
|
||||
unsigned group)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx;
|
||||
|
||||
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
||||
sirfsoc_pinmux_endisable(spmx, selector, false);
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_get_funcs_count(struct pinctrl_dev *pmxdev)
|
||||
{
|
||||
return sirfsoc_pmxfunc_cnt;
|
||||
}
|
||||
|
||||
static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev,
|
||||
unsigned selector)
|
||||
{
|
||||
return sirfsoc_pmx_functions[selector].name;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
|
||||
const char * const **groups,
|
||||
unsigned * const num_groups)
|
||||
{
|
||||
*groups = sirfsoc_pmx_functions[selector].groups;
|
||||
*num_groups = sirfsoc_pmx_functions[selector].num_groups;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
|
||||
struct pinctrl_gpio_range *range, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_pmx *spmx;
|
||||
|
||||
int group = range->id;
|
||||
|
||||
u32 muxval;
|
||||
|
||||
spmx = pinctrl_dev_get_drvdata(pmxdev);
|
||||
|
||||
if (!spmx->is_marco) {
|
||||
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
|
||||
muxval = muxval | (1 << (offset - range->pin_base));
|
||||
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
|
||||
} else {
|
||||
writel(1 << (offset - range->pin_base), spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(group));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinmux_ops sirfsoc_pinmux_ops = {
|
||||
.enable = sirfsoc_pinmux_enable,
|
||||
.disable = sirfsoc_pinmux_disable,
|
||||
.get_functions_count = sirfsoc_pinmux_get_funcs_count,
|
||||
.get_function_name = sirfsoc_pinmux_get_func_name,
|
||||
.get_function_groups = sirfsoc_pinmux_get_groups,
|
||||
.gpio_request_enable = sirfsoc_pinmux_request_gpio,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc sirfsoc_pinmux_desc = {
|
||||
.name = DRIVER_NAME,
|
||||
.pctlops = &sirfsoc_pctrl_ops,
|
||||
.pmxops = &sirfsoc_pinmux_ops,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Todo: bind irq_chip to every pinctrl_gpio_range
|
||||
*/
|
||||
static struct pinctrl_gpio_range sirfsoc_gpio_ranges[] = {
|
||||
{
|
||||
.name = "sirfsoc-gpio*",
|
||||
.id = 0,
|
||||
.base = 0,
|
||||
.pin_base = 0,
|
||||
.npins = 32,
|
||||
}, {
|
||||
.name = "sirfsoc-gpio*",
|
||||
.id = 1,
|
||||
.base = 32,
|
||||
.pin_base = 32,
|
||||
.npins = 32,
|
||||
}, {
|
||||
.name = "sirfsoc-gpio*",
|
||||
.id = 2,
|
||||
.base = 64,
|
||||
.pin_base = 64,
|
||||
.npins = 32,
|
||||
}, {
|
||||
.name = "sirfsoc-gpio*",
|
||||
.id = 3,
|
||||
.base = 96,
|
||||
.pin_base = 96,
|
||||
.npins = 19,
|
||||
},
|
||||
};
|
||||
|
||||
static void __iomem *sirfsoc_rsc_of_iomap(void)
|
||||
{
|
||||
const struct of_device_id rsc_ids[] = {
|
||||
{ .compatible = "sirf,prima2-rsc" },
|
||||
{ .compatible = "sirf,marco-rsc" },
|
||||
{}
|
||||
};
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, rsc_ids);
|
||||
if (!np)
|
||||
panic("unable to find compatible rsc node in dtb\n");
|
||||
|
||||
return of_iomap(np, 0);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc,
|
||||
const struct of_phandle_args *gpiospec,
|
||||
u32 *flags)
|
||||
{
|
||||
if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * SIRFSOC_GPIO_BANK_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (gc != &sgpio_bank[gpiospec->args[0] / SIRFSOC_GPIO_BANK_SIZE].chip.gc)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags)
|
||||
*flags = gpiospec->args[1];
|
||||
|
||||
return gpiospec->args[0] % SIRFSOC_GPIO_BANK_SIZE;
|
||||
}
|
||||
|
||||
static const struct of_device_id pinmux_ids[] = {
|
||||
{ .compatible = "sirf,prima2-pinctrl", .data = &prima2_pinctrl_data, },
|
||||
{ .compatible = "sirf,atlas6-pinctrl", .data = &atlas6_pinctrl_data, },
|
||||
{ .compatible = "sirf,marco-pinctrl", .data = &prima2_pinctrl_data, },
|
||||
{}
|
||||
};
|
||||
|
||||
static int sirfsoc_pinmux_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct sirfsoc_pmx *spmx;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct sirfsoc_pinctrl_data *pdata;
|
||||
int i;
|
||||
|
||||
/* Create state holders etc for this driver */
|
||||
spmx = devm_kzalloc(&pdev->dev, sizeof(*spmx), GFP_KERNEL);
|
||||
if (!spmx)
|
||||
return -ENOMEM;
|
||||
|
||||
spmx->dev = &pdev->dev;
|
||||
|
||||
platform_set_drvdata(pdev, spmx);
|
||||
|
||||
spmx->gpio_virtbase = of_iomap(np, 0);
|
||||
if (!spmx->gpio_virtbase) {
|
||||
dev_err(&pdev->dev, "can't map gpio registers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spmx->rsc_virtbase = sirfsoc_rsc_of_iomap();
|
||||
if (!spmx->rsc_virtbase) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&pdev->dev, "can't map rsc registers\n");
|
||||
goto out_no_rsc_remap;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
|
||||
spmx->is_marco = 1;
|
||||
|
||||
pdata = of_match_node(pinmux_ids, np)->data;
|
||||
sirfsoc_pin_groups = pdata->grps;
|
||||
sirfsoc_pingrp_cnt = pdata->grps_cnt;
|
||||
sirfsoc_pmx_functions = pdata->funcs;
|
||||
sirfsoc_pmxfunc_cnt = pdata->funcs_cnt;
|
||||
sirfsoc_pinmux_desc.pins = pdata->pads;
|
||||
sirfsoc_pinmux_desc.npins = pdata->pads_cnt;
|
||||
|
||||
|
||||
/* Now register the pin controller and all pins it handles */
|
||||
spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx);
|
||||
if (!spmx->pmx) {
|
||||
dev_err(&pdev->dev, "could not register SIRFSOC pinmux driver\n");
|
||||
ret = -EINVAL;
|
||||
goto out_no_pmx;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sirfsoc_gpio_ranges); i++) {
|
||||
sirfsoc_gpio_ranges[i].gc = &sgpio_bank[i].chip.gc;
|
||||
pinctrl_add_gpio_range(spmx->pmx, &sirfsoc_gpio_ranges[i]);
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "initialized SIRFSOC pinmux driver\n");
|
||||
|
||||
return 0;
|
||||
|
||||
out_no_pmx:
|
||||
iounmap(spmx->rsc_virtbase);
|
||||
out_no_rsc_remap:
|
||||
iounmap(spmx->gpio_virtbase);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int sirfsoc_pinmux_suspend_noirq(struct device *dev)
|
||||
{
|
||||
int i, j;
|
||||
struct sirfsoc_pmx *spmx = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for (j = 0; j < SIRFSOC_GPIO_BANK_SIZE; j++) {
|
||||
spmx->gpio_regs[i][j] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_CTRL(i, j));
|
||||
}
|
||||
spmx->ints_regs[i] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_INT_STATUS(i));
|
||||
spmx->paden_regs[i] = readl(spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(i));
|
||||
}
|
||||
spmx->dspen_regs = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_DSP_EN0);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
spmx->rsc_regs[i] = readl(spmx->rsc_virtbase + 4 * i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_pinmux_resume_noirq(struct device *dev)
|
||||
{
|
||||
int i, j;
|
||||
struct sirfsoc_pmx *spmx = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for (j = 0; j < SIRFSOC_GPIO_BANK_SIZE; j++) {
|
||||
writel(spmx->gpio_regs[i][j], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_CTRL(i, j));
|
||||
}
|
||||
writel(spmx->ints_regs[i], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_INT_STATUS(i));
|
||||
writel(spmx->paden_regs[i], spmx->gpio_virtbase +
|
||||
SIRFSOC_GPIO_PAD_EN(i));
|
||||
}
|
||||
writel(spmx->dspen_regs, spmx->gpio_virtbase + SIRFSOC_GPIO_DSP_EN0);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
writel(spmx->rsc_regs[i], spmx->rsc_virtbase + 4 * i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops sirfsoc_pinmux_pm_ops = {
|
||||
.suspend_noirq = sirfsoc_pinmux_suspend_noirq,
|
||||
.resume_noirq = sirfsoc_pinmux_resume_noirq,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver sirfsoc_pinmux_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = pinmux_ids,
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.pm = &sirfsoc_pinmux_pm_ops,
|
||||
#endif
|
||||
},
|
||||
.probe = sirfsoc_pinmux_probe,
|
||||
};
|
||||
|
||||
static int __init sirfsoc_pinmux_init(void)
|
||||
{
|
||||
return platform_driver_register(&sirfsoc_pinmux_driver);
|
||||
}
|
||||
arch_initcall(sirfsoc_pinmux_init);
|
||||
|
||||
static inline int sirfsoc_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = container_of(to_of_mm_gpio_chip(chip),
|
||||
struct sirfsoc_gpio_bank, chip);
|
||||
|
||||
return irq_create_mapping(bank->domain, offset);
|
||||
}
|
||||
|
||||
static inline int sirfsoc_gpio_to_offset(unsigned int gpio)
|
||||
{
|
||||
return gpio % SIRFSOC_GPIO_BANK_SIZE;
|
||||
}
|
||||
|
||||
static inline struct sirfsoc_gpio_bank *sirfsoc_gpio_to_bank(unsigned int gpio)
|
||||
{
|
||||
return &sgpio_bank[gpio / SIRFSOC_GPIO_BANK_SIZE];
|
||||
}
|
||||
|
||||
static inline struct sirfsoc_gpio_bank *sirfsoc_irqchip_to_bank(struct gpio_chip *chip)
|
||||
{
|
||||
return container_of(to_of_mm_gpio_chip(chip), struct sirfsoc_gpio_bank, chip);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio_lock, flags);
|
||||
|
||||
val = readl(bank->chip.regs + offset);
|
||||
|
||||
writel(val, bank->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio_lock, flags);
|
||||
}
|
||||
|
||||
static void __sirfsoc_gpio_irq_mask(struct sirfsoc_gpio_bank *bank, int idx)
|
||||
{
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio_lock, flags);
|
||||
|
||||
val = readl(bank->chip.regs + offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
|
||||
writel(val, bank->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio_lock, flags);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
|
||||
__sirfsoc_gpio_irq_mask(bank, d->hwirq % SIRFSOC_GPIO_BANK_SIZE);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio_lock, flags);
|
||||
|
||||
val = readl(bank->chip.regs + offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
writel(val, bank->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio_lock, flags);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
|
||||
u32 val, offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio_lock, flags);
|
||||
|
||||
val = readl(bank->chip.regs + offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_NONE:
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
val &= ~SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
|
||||
SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
val &= ~(SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
|
||||
val &= ~(SIRFSOC_GPIO_CTL_INTR_LOW_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
|
||||
break;
|
||||
}
|
||||
|
||||
writel(val, bank->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip sirfsoc_irq_chip = {
|
||||
.name = "sirf-gpio-irq",
|
||||
.irq_ack = sirfsoc_gpio_irq_ack,
|
||||
.irq_mask = sirfsoc_gpio_irq_mask,
|
||||
.irq_unmask = sirfsoc_gpio_irq_unmask,
|
||||
.irq_set_type = sirfsoc_gpio_irq_type,
|
||||
};
|
||||
|
||||
static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = irq_get_handler_data(irq);
|
||||
u32 status, ctrl;
|
||||
int idx = 0;
|
||||
struct irq_chip *chip = irq_get_chip(irq);
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
status = readl(bank->chip.regs + SIRFSOC_GPIO_INT_STATUS(bank->id));
|
||||
if (!status) {
|
||||
printk(KERN_WARNING
|
||||
"%s: gpio id %d status %#x no interrupt is flaged\n",
|
||||
__func__, bank->id, status);
|
||||
handle_bad_irq(irq, desc);
|
||||
return;
|
||||
}
|
||||
|
||||
while (status) {
|
||||
ctrl = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, idx));
|
||||
|
||||
/*
|
||||
* Here we must check whether the corresponding GPIO's interrupt
|
||||
* has been enabled, otherwise just skip it
|
||||
*/
|
||||
if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) {
|
||||
pr_debug("%s: gpio id %d idx %d happens\n",
|
||||
__func__, bank->id, idx);
|
||||
generic_handle_irq(irq_find_mapping(bank->domain, idx));
|
||||
}
|
||||
|
||||
idx++;
|
||||
status = status >> 1;
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static inline void sirfsoc_gpio_set_input(struct sirfsoc_gpio_bank *bank, unsigned ctrl_offset)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(bank->chip.regs + ctrl_offset);
|
||||
val &= ~SIRFSOC_GPIO_CTL_OUT_EN_MASK;
|
||||
writel(val, bank->chip.regs + ctrl_offset);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
unsigned long flags;
|
||||
|
||||
if (pinctrl_request_gpio(chip->base + offset))
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
/*
|
||||
* default status:
|
||||
* set direction as input and mask irq
|
||||
*/
|
||||
sirfsoc_gpio_set_input(bank, SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
__sirfsoc_gpio_irq_mask(bank, offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
__sirfsoc_gpio_irq_mask(bank, offset);
|
||||
sirfsoc_gpio_set_input(bank, SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
pinctrl_free_gpio(chip->base + offset);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
int idx = sirfsoc_gpio_to_offset(gpio);
|
||||
unsigned long flags;
|
||||
unsigned offset;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
sirfsoc_gpio_set_input(bank, offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void sirfsoc_gpio_set_output(struct sirfsoc_gpio_bank *bank, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
u32 out_ctrl;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
out_ctrl = readl(bank->chip.regs + offset);
|
||||
if (value)
|
||||
out_ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
else
|
||||
out_ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
|
||||
out_ctrl &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
|
||||
out_ctrl |= SIRFSOC_GPIO_CTL_OUT_EN_MASK;
|
||||
writel(out_ctrl, bank->chip.regs + offset);
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
int idx = sirfsoc_gpio_to_offset(gpio);
|
||||
u32 offset;
|
||||
unsigned long flags;
|
||||
|
||||
offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
|
||||
|
||||
spin_lock_irqsave(&sgpio_lock, flags);
|
||||
|
||||
sirfsoc_gpio_set_output(bank, offset, value);
|
||||
|
||||
spin_unlock_irqrestore(&sgpio_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_get_value(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
val = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return !!(val & SIRFSOC_GPIO_CTL_DATAIN_MASK);
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
|
||||
u32 ctrl;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
|
||||
ctrl = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
if (value)
|
||||
ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
else
|
||||
ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
|
||||
writel(ctrl, bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
|
||||
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
struct sirfsoc_gpio_bank *bank = d->host_data;
|
||||
|
||||
if (!bank)
|
||||
return -EINVAL;
|
||||
|
||||
irq_set_chip(irq, &sirfsoc_irq_chip);
|
||||
irq_set_handler(irq, handle_level_irq);
|
||||
irq_set_chip_data(irq, bank);
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops sirfsoc_gpio_irq_simple_ops = {
|
||||
.map = sirfsoc_gpio_irq_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
||||
static void sirfsoc_gpio_set_pullup(const u32 *pullups)
|
||||
{
|
||||
int i, n;
|
||||
const unsigned long *p = (const unsigned long *)pullups;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for_each_set_bit(n, p + i, BITS_PER_LONG) {
|
||||
u32 offset = SIRFSOC_GPIO_CTRL(i, n);
|
||||
u32 val = readl(sgpio_bank[i].chip.regs + offset);
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_MASK;
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
|
||||
writel(val, sgpio_bank[i].chip.regs + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sirfsoc_gpio_set_pulldown(const u32 *pulldowns)
|
||||
{
|
||||
int i, n;
|
||||
const unsigned long *p = (const unsigned long *)pulldowns;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
for_each_set_bit(n, p + i, BITS_PER_LONG) {
|
||||
u32 offset = SIRFSOC_GPIO_CTRL(i, n);
|
||||
u32 val = readl(sgpio_bank[i].chip.regs + offset);
|
||||
val |= SIRFSOC_GPIO_CTL_PULL_MASK;
|
||||
val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
|
||||
writel(val, sgpio_bank[i].chip.regs + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int sirfsoc_gpio_probe(struct device_node *np)
|
||||
{
|
||||
int i, err = 0;
|
||||
struct sirfsoc_gpio_bank *bank;
|
||||
void *regs;
|
||||
struct platform_device *pdev;
|
||||
bool is_marco = false;
|
||||
|
||||
u32 pullups[SIRFSOC_GPIO_NO_OF_BANKS], pulldowns[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
|
||||
pdev = of_find_device_by_node(np);
|
||||
if (!pdev)
|
||||
return -ENODEV;
|
||||
|
||||
regs = of_iomap(np, 0);
|
||||
if (!regs)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
|
||||
is_marco = 1;
|
||||
|
||||
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
|
||||
bank = &sgpio_bank[i];
|
||||
spin_lock_init(&bank->lock);
|
||||
bank->chip.gc.request = sirfsoc_gpio_request;
|
||||
bank->chip.gc.free = sirfsoc_gpio_free;
|
||||
bank->chip.gc.direction_input = sirfsoc_gpio_direction_input;
|
||||
bank->chip.gc.get = sirfsoc_gpio_get_value;
|
||||
bank->chip.gc.direction_output = sirfsoc_gpio_direction_output;
|
||||
bank->chip.gc.set = sirfsoc_gpio_set_value;
|
||||
bank->chip.gc.to_irq = sirfsoc_gpio_to_irq;
|
||||
bank->chip.gc.base = i * SIRFSOC_GPIO_BANK_SIZE;
|
||||
bank->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE;
|
||||
bank->chip.gc.label = kstrdup(np->full_name, GFP_KERNEL);
|
||||
bank->chip.gc.of_node = np;
|
||||
bank->chip.gc.of_xlate = sirfsoc_gpio_of_xlate;
|
||||
bank->chip.gc.of_gpio_n_cells = 2;
|
||||
bank->chip.regs = regs;
|
||||
bank->id = i;
|
||||
bank->is_marco = is_marco;
|
||||
bank->parent_irq = platform_get_irq(pdev, i);
|
||||
if (bank->parent_irq < 0) {
|
||||
err = bank->parent_irq;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = gpiochip_add(&bank->chip.gc);
|
||||
if (err) {
|
||||
pr_err("%s: error in probe function with status %d\n",
|
||||
np->full_name, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bank->domain = irq_domain_add_linear(np, SIRFSOC_GPIO_BANK_SIZE,
|
||||
&sirfsoc_gpio_irq_simple_ops, bank);
|
||||
|
||||
if (!bank->domain) {
|
||||
pr_err("%s: Failed to create irqdomain\n", np->full_name);
|
||||
err = -ENOSYS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
irq_set_chained_handler(bank->parent_irq, sirfsoc_gpio_handle_irq);
|
||||
irq_set_handler_data(bank->parent_irq, bank);
|
||||
}
|
||||
|
||||
if (!of_property_read_u32_array(np, "sirf,pullups", pullups,
|
||||
SIRFSOC_GPIO_NO_OF_BANKS))
|
||||
sirfsoc_gpio_set_pullup(pullups);
|
||||
|
||||
if (!of_property_read_u32_array(np, "sirf,pulldowns", pulldowns,
|
||||
SIRFSOC_GPIO_NO_OF_BANKS))
|
||||
sirfsoc_gpio_set_pulldown(pulldowns);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
iounmap(regs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __init sirfsoc_gpio_init(void)
|
||||
{
|
||||
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, pinmux_ids);
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
return sirfsoc_gpio_probe(np);
|
||||
}
|
||||
subsys_initcall(sirfsoc_gpio_init);
|
||||
|
||||
MODULE_AUTHOR("Rongjun Ying <[email protected]>, "
|
||||
"Yuping Luo <[email protected]>, "
|
||||
"Barry Song <[email protected]>");
|
||||
MODULE_DESCRIPTION("SIRFSOC pin control driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
116
drivers/pinctrl/sirf/pinctrl-sirf.h
Normal file
116
drivers/pinctrl/sirf/pinctrl-sirf.h
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* pinmux driver shared headfile for CSR SiRFsoc
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __PINMUX_SIRF_H__
|
||||
#define __PINMUX_SIRF_H__
|
||||
|
||||
#define SIRFSOC_NUM_PADS 622
|
||||
#define SIRFSOC_RSC_PIN_MUX 0x4
|
||||
|
||||
#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
|
||||
#define SIRFSOC_GPIO_PAD_EN_CLR(g) ((g)*0x100 + 0x90)
|
||||
#define SIRFSOC_GPIO_CTRL(g, i) ((g)*0x100 + (i)*4)
|
||||
#define SIRFSOC_GPIO_DSP_EN0 (0x80)
|
||||
#define SIRFSOC_GPIO_INT_STATUS(g) ((g)*0x100 + 0x8C)
|
||||
|
||||
#define SIRFSOC_GPIO_CTL_INTR_LOW_MASK 0x1
|
||||
#define SIRFSOC_GPIO_CTL_INTR_HIGH_MASK 0x2
|
||||
#define SIRFSOC_GPIO_CTL_INTR_TYPE_MASK 0x4
|
||||
#define SIRFSOC_GPIO_CTL_INTR_EN_MASK 0x8
|
||||
#define SIRFSOC_GPIO_CTL_INTR_STS_MASK 0x10
|
||||
#define SIRFSOC_GPIO_CTL_OUT_EN_MASK 0x20
|
||||
#define SIRFSOC_GPIO_CTL_DATAOUT_MASK 0x40
|
||||
#define SIRFSOC_GPIO_CTL_DATAIN_MASK 0x80
|
||||
#define SIRFSOC_GPIO_CTL_PULL_MASK 0x100
|
||||
#define SIRFSOC_GPIO_CTL_PULL_HIGH 0x200
|
||||
#define SIRFSOC_GPIO_CTL_DSP_INT 0x400
|
||||
|
||||
#define SIRFSOC_GPIO_NO_OF_BANKS 5
|
||||
#define SIRFSOC_GPIO_BANK_SIZE 32
|
||||
#define SIRFSOC_GPIO_NUM(bank, index) (((bank)*(32)) + (index))
|
||||
|
||||
/**
|
||||
* @dev: a pointer back to containing device
|
||||
* @virtbase: the offset to the controller in virtual memory
|
||||
*/
|
||||
struct sirfsoc_pmx {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pmx;
|
||||
void __iomem *gpio_virtbase;
|
||||
void __iomem *rsc_virtbase;
|
||||
u32 gpio_regs[SIRFSOC_GPIO_NO_OF_BANKS][SIRFSOC_GPIO_BANK_SIZE];
|
||||
u32 ints_regs[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
u32 paden_regs[SIRFSOC_GPIO_NO_OF_BANKS];
|
||||
u32 dspen_regs;
|
||||
u32 rsc_regs[3];
|
||||
bool is_marco;
|
||||
};
|
||||
|
||||
/* SIRFSOC_GPIO_PAD_EN set */
|
||||
struct sirfsoc_muxmask {
|
||||
unsigned long group;
|
||||
unsigned long mask;
|
||||
};
|
||||
|
||||
struct sirfsoc_padmux {
|
||||
unsigned long muxmask_counts;
|
||||
const struct sirfsoc_muxmask *muxmask;
|
||||
/* RSC_PIN_MUX set */
|
||||
unsigned long funcmask;
|
||||
unsigned long funcval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sirfsoc_pin_group - describes a SiRFprimaII pin group
|
||||
* @name: the name of this specific pin group
|
||||
* @pins: an array of discrete physical pins used in this group, taken
|
||||
* from the driver-local pin enumeration space
|
||||
* @num_pins: the number of pins in this group array, i.e. the number of
|
||||
* elements in .pins so we can iterate over that array
|
||||
*/
|
||||
struct sirfsoc_pin_group {
|
||||
const char *name;
|
||||
const unsigned int *pins;
|
||||
const unsigned num_pins;
|
||||
};
|
||||
|
||||
#define SIRFSOC_PIN_GROUP(n, p) \
|
||||
{ \
|
||||
.name = n, \
|
||||
.pins = p, \
|
||||
.num_pins = ARRAY_SIZE(p), \
|
||||
}
|
||||
|
||||
struct sirfsoc_pmx_func {
|
||||
const char *name;
|
||||
const char * const *groups;
|
||||
const unsigned num_groups;
|
||||
const struct sirfsoc_padmux *padmux;
|
||||
};
|
||||
|
||||
#define SIRFSOC_PMX_FUNCTION(n, g, m) \
|
||||
{ \
|
||||
.name = n, \
|
||||
.groups = g, \
|
||||
.num_groups = ARRAY_SIZE(g), \
|
||||
.padmux = &m, \
|
||||
}
|
||||
|
||||
struct sirfsoc_pinctrl_data {
|
||||
struct pinctrl_pin_desc *pads;
|
||||
int pads_cnt;
|
||||
struct sirfsoc_pin_group *grps;
|
||||
int grps_cnt;
|
||||
struct sirfsoc_pmx_func *funcs;
|
||||
int funcs_cnt;
|
||||
};
|
||||
|
||||
extern struct sirfsoc_pinctrl_data prima2_pinctrl_data;
|
||||
extern struct sirfsoc_pinctrl_data atlas6_pinctrl_data;
|
||||
|
||||
#endif
|
||||
|
|
@ -441,7 +441,7 @@ static int spear310_p2o(int pin)
|
|||
return offset;
|
||||
}
|
||||
|
||||
int spear310_o2p(int offset)
|
||||
static int spear310_o2p(int offset)
|
||||
{
|
||||
if (offset <= 3)
|
||||
return 101 - offset;
|
||||
|
|
@ -528,18 +528,13 @@ static int plgpio_probe(struct platform_device *pdev)
|
|||
struct resource *res;
|
||||
int ret, irq, i;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
|
||||
if (!plgpio) {
|
||||
dev_err(&pdev->dev, "memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
plgpio->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(plgpio->base))
|
||||
return PTR_ERR(plgpio->base);
|
||||
|
|
|
|||
|
|
@ -569,11 +569,9 @@ int wmt_pinctrl_probe(struct platform_device *pdev,
|
|||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->base = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (!data->base) {
|
||||
dev_err(&pdev->dev, "failed to map memory resource\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
data->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(data->base))
|
||||
return PTR_ERR(data->base);
|
||||
|
||||
wmt_desc.pins = data->pins;
|
||||
wmt_desc.npins = data->npins;
|
||||
|
|
|
|||
Loading…
Reference in a new issue