diff options
Diffstat (limited to 'drivers')
168 files changed, 7023 insertions, 2025 deletions
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index 4251570610c9..8a3f51f7b1b9 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig @@ -11,12 +11,15 @@ config REGMAP config REGMAP_I2C tristate + depends on I2C config REGMAP_SPI tristate + depends on SPI config REGMAP_SPMI tristate + depends on SPMI config REGMAP_MMIO tristate diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index bfc90b8547f2..0da5865df5b1 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -49,8 +49,10 @@ struct regmap_async { }; struct regmap { - struct mutex mutex; - spinlock_t spinlock; + union { + struct mutex mutex; + spinlock_t spinlock; + }; unsigned long spinlock_flags; regmap_lock lock; regmap_unlock unlock; diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 5617da6dc898..f1280dc356d0 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -269,8 +269,11 @@ static int regcache_default_sync(struct regmap *map, unsigned int min, map->cache_bypass = 1; ret = _regmap_write(map, reg, val); map->cache_bypass = 0; - if (ret) + if (ret) { + dev_err(map->dev, "Unable to sync register %#x. %d\n", + reg, ret); return ret; + } dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val); } @@ -615,8 +618,11 @@ static int regcache_sync_block_single(struct regmap *map, void *block, ret = _regmap_write(map, regtmp, val); map->cache_bypass = 0; - if (ret != 0) + if (ret != 0) { + dev_err(map->dev, "Unable to sync register %#x. %d\n", + regtmp, ret); return ret; + } dev_dbg(map->dev, "Synced register %#x, value %#x\n", regtmp, val); } @@ -641,6 +647,9 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data, map->cache_bypass = 1; ret = _regmap_raw_write(map, base, *data, count * val_bytes); + if (ret) + dev_err(map->dev, "Unable to sync registers %#x-%#x. %d\n", + base, cur - map->reg_stride, ret); map->cache_bypass = 0; diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 0c94b661c16f..5799a0b9e6cc 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -473,6 +473,7 @@ void regmap_debugfs_init(struct regmap *map, const char *name) { struct rb_node *next; struct regmap_range_node *range_node; + const char *devname = "dummy"; /* If we don't have the debugfs root yet, postpone init */ if (!regmap_debugfs_root) { @@ -491,12 +492,15 @@ void regmap_debugfs_init(struct regmap *map, const char *name) INIT_LIST_HEAD(&map->debugfs_off_cache); mutex_init(&map->cache_lock); + if (map->dev) + devname = dev_name(map->dev); + if (name) { map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", - dev_name(map->dev), name); + devname, name); name = map->debugfs_name; } else { - name = dev_name(map->dev); + name = devname; } map->debugfs = debugfs_create_dir(name, regmap_debugfs_root); diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index f2281af24ec6..d2f8a818d200 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -477,7 +477,7 @@ static enum regmap_endian regmap_get_val_endian(struct device *dev, const struct regmap_bus *bus, const struct regmap_config *config) { - struct device_node *np = dev->of_node; + struct device_node *np; enum regmap_endian endian; /* Retrieve the endianness specification from the regmap config */ @@ -487,15 +487,20 @@ static enum regmap_endian regmap_get_val_endian(struct device *dev, if (endian != REGMAP_ENDIAN_DEFAULT) return endian; - /* Parse the device's DT node for an endianness specification */ - if (of_property_read_bool(np, "big-endian")) - endian = REGMAP_ENDIAN_BIG; - else if (of_property_read_bool(np, "little-endian")) - endian = REGMAP_ENDIAN_LITTLE; + /* If the dev and dev->of_node exist try to get endianness from DT */ + if (dev && dev->of_node) { + np = dev->of_node; - /* If the endianness was specified in DT, use that */ - if (endian != REGMAP_ENDIAN_DEFAULT) - return endian; + /* Parse the device's DT node for an endianness specification */ + if (of_property_read_bool(np, "big-endian")) + endian = REGMAP_ENDIAN_BIG; + else if (of_property_read_bool(np, "little-endian")) + endian = REGMAP_ENDIAN_LITTLE; + + /* If the endianness was specified in DT, use that */ + if (endian != REGMAP_ENDIAN_DEFAULT) + return endian; + } /* Retrieve the endianness specification from the bus config */ if (bus && bus->val_format_endian_default) @@ -1460,7 +1465,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, } #ifdef LOG_DEVICE - if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) + if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0) dev_info(map->dev, "%x <= %x\n", reg, val); #endif @@ -1711,6 +1716,9 @@ out: } else { void *wval; + if (!val_count) + return -EINVAL; + wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); if (!wval) { dev_err(map->dev, "Error in memory allocation\n"); @@ -2110,7 +2118,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg, ret = map->reg_read(context, reg, val); if (ret == 0) { #ifdef LOG_DEVICE - if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) + if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0) dev_info(map->dev, "%x => %x\n", reg, *val); #endif diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index e6db9381b2c7..f816211f062f 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -2796,7 +2796,6 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) = IPMI_CHANNEL_MEDIUM_IPMB; intf->channels[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; - rv = -ENOSYS; intf->curr_channel = IPMI_MAX_CHANNELS; wake_up(&intf->waitq); @@ -2821,12 +2820,12 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) if (rv) { /* Got an error somehow, just give up. */ + printk(KERN_WARNING PFX + "Error sending channel information for channel" + " %d: %d\n", intf->curr_channel, rv); + intf->curr_channel = IPMI_MAX_CHANNELS; wake_up(&intf->waitq); - - printk(KERN_WARNING PFX - "Error sending channel information: %d\n", - rv); } } out: @@ -2964,8 +2963,12 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, intf->null_user_handler = channel_handler; intf->curr_channel = 0; rv = send_channel_info_cmd(intf, 0); - if (rv) + if (rv) { + printk(KERN_WARNING PFX + "Error sending channel information for channel" + " 0, %d\n", rv); goto out; + } /* Wait for the channel info to be read. */ wait_event(intf->waitq, diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 5d665680ae33..5c4e1f625bbb 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -965,9 +965,9 @@ static inline int ipmi_si_is_busy(struct timespec *ts) return ts->tv_nsec != -1; } -static int ipmi_thread_busy_wait(enum si_sm_result smi_result, - const struct smi_info *smi_info, - struct timespec *busy_until) +static inline int ipmi_thread_busy_wait(enum si_sm_result smi_result, + const struct smi_info *smi_info, + struct timespec *busy_until) { unsigned int max_busy_us = 0; @@ -2658,6 +2658,9 @@ static int ipmi_probe(struct platform_device *dev) if (!match) return -EINVAL; + if (!of_device_is_available(np)) + return -EINVAL; + ret = of_address_to_resource(np, 0, &resource); if (ret) { dev_warn(&dev->dev, PFX "invalid address from OF\n"); @@ -3655,6 +3658,9 @@ static void cleanup_one_si(struct smi_info *to_clean) if (!to_clean) return; + if (to_clean->dev) + dev_set_drvdata(to_clean->dev, NULL); + list_del(&to_clean->link); /* Tell the driver that we are shutting down. */ diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6e93e7f98358..61190f6b4829 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1658,10 +1658,8 @@ void cpufreq_suspend(void) if (!cpufreq_driver) return; - cpufreq_suspended = true; - if (!has_target()) - return; + goto suspend; pr_debug("%s: Suspending Governors\n", __func__); @@ -1674,6 +1672,9 @@ void cpufreq_suspend(void) pr_err("%s: Failed to suspend driver: %p\n", __func__, policy); } + +suspend: + cpufreq_suspended = true; } /** diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c index c1320528b9d0..6bd69adc3c5e 100644 --- a/drivers/cpufreq/integrator-cpufreq.c +++ b/drivers/cpufreq/integrator-cpufreq.c @@ -213,9 +213,9 @@ static int __init integrator_cpufreq_probe(struct platform_device *pdev) return cpufreq_register_driver(&integrator_driver); } -static void __exit integrator_cpufreq_remove(struct platform_device *pdev) +static int __exit integrator_cpufreq_remove(struct platform_device *pdev) { - cpufreq_unregister_driver(&integrator_driver); + return cpufreq_unregister_driver(&integrator_driver); } static const struct of_device_id integrator_cpufreq_match[] = { diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 728a2d879499..4d2c8e861089 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -204,7 +204,6 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy, u32 input_buffer; int cpu; - spin_lock(&pcc_lock); cpu = policy->cpu; pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu); @@ -216,6 +215,7 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy, freqs.old = policy->cur; freqs.new = target_freq; cpufreq_freq_transition_begin(policy, &freqs); + spin_lock(&pcc_lock); input_buffer = 0x1 | (((target_freq * 100) / (ioread32(&pcch_hdr->nominal) * 1000)) << 8); diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 9b1ea0ef59af..a016490c95ae 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -427,18 +427,6 @@ config DMA_OF comment "DMA Clients" depends on DMA_ENGINE -config NET_DMA - bool "Network: TCP receive copy offload" - depends on DMA_ENGINE && NET - default (INTEL_IOATDMA || FSL_DMA) - depends on BROKEN - help - This enables the use of DMA engines in the network stack to - offload receive copy-to-user operations, freeing CPU cycles. - - Say Y here if you enabled INTEL_IOATDMA or FSL_DMA, otherwise - say N. - config ASYNC_TX_DMA bool "Async_tx: Offload support for the async_tx api" depends on DMA_ENGINE diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index c6adb925f0b9..cb626c179911 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -6,7 +6,6 @@ obj-$(CONFIG_DMA_VIRTUAL_CHANNELS) += virt-dma.o obj-$(CONFIG_DMA_ACPI) += acpi-dma.o obj-$(CONFIG_DMA_OF) += of-dma.o -obj-$(CONFIG_NET_DMA) += iovlock.o obj-$(CONFIG_INTEL_MID_DMAC) += intel_mid_dma.o obj-$(CONFIG_DMATEST) += dmatest.o obj-$(CONFIG_INTEL_IOATDMA) += ioat/ diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index d5d30ed863ce..24bfaf0b92ba 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -1081,110 +1081,6 @@ dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags) } EXPORT_SYMBOL(dmaengine_get_unmap_data); -/** - * dma_async_memcpy_pg_to_pg - offloaded copy from page to page - * @chan: DMA channel to offload copy to - * @dest_pg: destination page - * @dest_off: offset in page to copy to - * @src_pg: source page - * @src_off: offset in page to copy from - * @len: length - * - * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus - * address according to the DMA mapping API rules for streaming mappings. - * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident - * (kernel memory or locked user space pages). - */ -dma_cookie_t -dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg, - unsigned int dest_off, struct page *src_pg, unsigned int src_off, - size_t len) -{ - struct dma_device *dev = chan->device; - struct dma_async_tx_descriptor *tx; - struct dmaengine_unmap_data *unmap; - dma_cookie_t cookie; - unsigned long flags; - - unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOWAIT); - if (!unmap) - return -ENOMEM; - - unmap->to_cnt = 1; - unmap->from_cnt = 1; - unmap->addr[0] = dma_map_page(dev->dev, src_pg, src_off, len, - DMA_TO_DEVICE); - unmap->addr[1] = dma_map_page(dev->dev, dest_pg, dest_off, len, - DMA_FROM_DEVICE); - unmap->len = len; - flags = DMA_CTRL_ACK; - tx = dev->device_prep_dma_memcpy(chan, unmap->addr[1], unmap->addr[0], - len, flags); - - if (!tx) { - dmaengine_unmap_put(unmap); - return -ENOMEM; - } - - dma_set_unmap(tx, unmap); - cookie = tx->tx_submit(tx); - dmaengine_unmap_put(unmap); - - preempt_disable(); - __this_cpu_add(chan->local->bytes_transferred, len); - __this_cpu_inc(chan->local->memcpy_count); - preempt_enable(); - - return cookie; -} -EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg); - -/** - * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses - * @chan: DMA channel to offload copy to - * @dest: destination address (virtual) - * @src: source address (virtual) - * @len: length - * - * Both @dest and @src must be mappable to a bus address according to the - * DMA mapping API rules for streaming mappings. - * Both @dest and @src must stay memory resident (kernel memory or locked - * user space pages). - */ -dma_cookie_t -dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest, - void *src, size_t len) -{ - return dma_async_memcpy_pg_to_pg(chan, virt_to_page(dest), - (unsigned long) dest & ~PAGE_MASK, - virt_to_page(src), - (unsigned long) src & ~PAGE_MASK, len); -} -EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf); - -/** - * dma_async_memcpy_buf_to_pg - offloaded copy from address to page - * @chan: DMA channel to offload copy to - * @page: destination page - * @offset: offset in page to copy to - * @kdata: source address (virtual) - * @len: length - * - * Both @page/@offset and @kdata must be mappable to a bus address according - * to the DMA mapping API rules for streaming mappings. - * Both @page/@offset and @kdata must stay memory resident (kernel memory or - * locked user space pages) - */ -dma_cookie_t -dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page, - unsigned int offset, void *kdata, size_t len) -{ - return dma_async_memcpy_pg_to_pg(chan, page, offset, - virt_to_page(kdata), - (unsigned long) kdata & ~PAGE_MASK, len); -} -EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg); - void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx, struct dma_chan *chan) { diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index e27cec25c59e..a8d7809e2f4c 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -688,14 +688,14 @@ static int dmatest_func(void *data) runtime = ktime_us_delta(ktime_get(), ktime); ret = 0; +err_dstbuf: for (i = 0; thread->dsts[i]; i++) kfree(thread->dsts[i]); -err_dstbuf: kfree(thread->dsts); err_dsts: +err_srcbuf: for (i = 0; thread->srcs[i]; i++) kfree(thread->srcs[i]); -err_srcbuf: kfree(thread->srcs); err_srcs: kfree(pq_coefs); diff --git a/drivers/dma/ioat/dca.c b/drivers/dma/ioat/dca.c index 9e84d5bc9307..3b55bb8d969a 100644 --- a/drivers/dma/ioat/dca.c +++ b/drivers/dma/ioat/dca.c @@ -35,6 +35,7 @@ #include "dma.h" #include "registers.h" +#include "dma_v2.h" /* * Bit 7 of a tag map entry is the "valid" bit, if it is set then bits 0:6 @@ -147,7 +148,7 @@ static int ioat_dca_add_requester(struct dca_provider *dca, struct device *dev) u16 id; /* This implementation only supports PCI-Express */ - if (dev->bus != &pci_bus_type) + if (!dev_is_pci(dev)) return -ENODEV; pdev = to_pci_dev(dev); id = dcaid_from_pcidev(pdev); @@ -179,7 +180,7 @@ static int ioat_dca_remove_requester(struct dca_provider *dca, int i; /* This implementation only supports PCI-Express */ - if (dev->bus != &pci_bus_type) + if (!dev_is_pci(dev)) return -ENODEV; pdev = to_pci_dev(dev); @@ -320,7 +321,7 @@ static int ioat2_dca_add_requester(struct dca_provider *dca, struct device *dev) u16 global_req_table; /* This implementation only supports PCI-Express */ - if (dev->bus != &pci_bus_type) + if (!dev_is_pci(dev)) return -ENODEV; pdev = to_pci_dev(dev); id = dcaid_from_pcidev(pdev); @@ -354,7 +355,7 @@ static int ioat2_dca_remove_requester(struct dca_provider *dca, u16 global_req_table; /* This implementation only supports PCI-Express */ - if (dev->bus != &pci_bus_type) + if (!dev_is_pci(dev)) return -ENODEV; pdev = to_pci_dev(dev); @@ -496,7 +497,7 @@ static int ioat3_dca_add_requester(struct dca_provider *dca, struct device *dev) u16 global_req_table; /* This implementation only supports PCI-Express */ - if (dev->bus != &pci_bus_type) + if (!dev_is_pci(dev)) return -ENODEV; pdev = to_pci_dev(dev); id = dcaid_from_pcidev(pdev); @@ -530,7 +531,7 @@ static int ioat3_dca_remove_requester(struct dca_provider *dca, u16 global_req_table; /* This implementation only supports PCI-Express */ - if (dev->bus != &pci_bus_type) + if (!dev_is_pci(dev)) return -ENODEV; pdev = to_pci_dev(dev); diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 4e3549a16132..940c1502a8b5 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -947,7 +947,7 @@ msix: for (i = 0; i < msixcnt; i++) device->msix_entries[i].entry = i; - err = pci_enable_msix(pdev, device->msix_entries, msixcnt); + err = pci_enable_msix_exact(pdev, device->msix_entries, msixcnt); if (err) goto msi; @@ -1222,7 +1222,6 @@ int ioat1_dma_probe(struct ioatdma_device *device, int dca) err = ioat_probe(device); if (err) return err; - ioat_set_tcp_copy_break(4096); err = ioat_register(device); if (err) return err; diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index e982f00a9843..d63f68b1aa35 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -214,13 +214,6 @@ __dump_desc_dbg(struct ioat_chan_common *chan, struct ioat_dma_descriptor *hw, #define dump_desc_dbg(c, d) \ ({ if (d) __dump_desc_dbg(&c->base, d->hw, &d->txd, desc_id(d)); 0; }) -static inline void ioat_set_tcp_copy_break(unsigned long copybreak) -{ - #ifdef CONFIG_NET_DMA - sysctl_tcp_dma_copybreak = copybreak; - #endif -} - static inline struct ioat_chan_common * ioat_chan_by_index(struct ioatdma_device *device, int index) { diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 8d1058085eeb..695483e6be32 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c @@ -735,7 +735,8 @@ int ioat2_check_space_lock(struct ioat2_dma_chan *ioat, int num_descs) * called under bh_disabled so we need to trigger the timer * event directly */ - if (jiffies > chan->timer.expires && timer_pending(&chan->timer)) { + if (time_is_before_jiffies(chan->timer.expires) + && timer_pending(&chan->timer)) { struct ioatdma_device *device = chan->device; mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT); @@ -899,7 +900,6 @@ int ioat2_dma_probe(struct ioatdma_device *device, int dca) err = ioat_probe(device); if (err) return err; - ioat_set_tcp_copy_break(2048); list_for_each_entry(c, &dma->channels, device_node) { chan = to_chan_common(c); diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index b9b38a1cf92f..895f869d6c2c 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -740,7 +740,7 @@ ioat3_prep_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src, return __ioat3_prep_xor_lock(chan, NULL, dest, src, src_cnt, len, flags); } -struct dma_async_tx_descriptor * +static struct dma_async_tx_descriptor * ioat3_prep_xor_val(struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt, size_t len, enum sum_check_flags *result, unsigned long flags) @@ -1091,7 +1091,7 @@ ioat3_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, } } -struct dma_async_tx_descriptor * +static struct dma_async_tx_descriptor * ioat3_prep_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src, unsigned int src_cnt, const unsigned char *scf, size_t len, enum sum_check_flags *pqres, unsigned long flags) @@ -1133,7 +1133,7 @@ ioat3_prep_pqxor(struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src, flags); } -struct dma_async_tx_descriptor * +static struct dma_async_tx_descriptor * ioat3_prep_pqxor_val(struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt, size_t len, enum sum_check_flags *result, unsigned long flags) @@ -1655,7 +1655,6 @@ int ioat3_dma_probe(struct ioatdma_device *device, int dca) err = ioat_probe(device); if (err) return err; - ioat_set_tcp_copy_break(262144); list_for_each_entry(c, &dma->channels, device_node) { chan = to_chan_common(c); diff --git a/drivers/dma/iovlock.c b/drivers/dma/iovlock.c deleted file mode 100644 index bb48a57c2fc1..000000000000 --- a/drivers/dma/iovlock.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. - * Portions based on net/core/datagram.c and copyrighted by their authors. - * - * 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. - * - * This program is distributed in the hope that 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., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution in the - * file called COPYING. - */ - -/* - * This code allows the net stack to make use of a DMA engine for - * skb to iovec copies. - */ - -#include <linux/dmaengine.h> -#include <linux/pagemap.h> -#include <linux/slab.h> -#include <net/tcp.h> /* for memcpy_toiovec */ -#include <asm/io.h> -#include <asm/uaccess.h> - -static int num_pages_spanned(struct iovec *iov) -{ - return - ((PAGE_ALIGN((unsigned long)iov->iov_base + iov->iov_len) - - ((unsigned long)iov->iov_base & PAGE_MASK)) >> PAGE_SHIFT); -} - -/* - * Pin down all the iovec pages needed for len bytes. - * Return a struct dma_pinned_list to keep track of pages pinned down. - * - * We are allocating a single chunk of memory, and then carving it up into - * 3 sections, the latter 2 whose size depends on the number of iovecs and the - * total number of pages, respectively. - */ -struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) -{ - struct dma_pinned_list *local_list; - struct page **pages; - int i; - int ret; - int nr_iovecs = 0; - int iovec_len_used = 0; - int iovec_pages_used = 0; - - /* don't pin down non-user-based iovecs */ - if (segment_eq(get_fs(), KERNEL_DS)) - return NULL; - - /* determine how many iovecs/pages there are, up front */ - do { - iovec_len_used += iov[nr_iovecs].iov_len; - iovec_pages_used += num_pages_spanned(&iov[nr_iovecs]); - nr_iovecs++; - } while (iovec_len_used < len); - - /* single kmalloc for pinned list, page_list[], and the page arrays */ - local_list = kmalloc(sizeof(*local_list) - + (nr_iovecs * sizeof (struct dma_page_list)) - + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL); - if (!local_list) - goto out; - - /* list of pages starts right after the page list array */ - pages = (struct page **) &local_list->page_list[nr_iovecs]; - - local_list->nr_iovecs = 0; - - for (i = 0; i < nr_iovecs; i++) { - struct dma_page_list *page_list = &local_list->page_list[i]; - - len -= iov[i].iov_len; - - if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) - goto unpin; - - page_list->nr_pages = num_pages_spanned(&iov[i]); - page_list->base_address = iov[i].iov_base; - - page_list->pages = pages; - pages += page_list->nr_pages; - - /* pin pages down */ - down_read(¤t->mm->mmap_sem); - ret = get_user_pages( - current, - current->mm, - (unsigned long) iov[i].iov_base, - page_list->nr_pages, - 1, /* write */ - 0, /* force */ - page_list->pages, - NULL); - up_read(¤t->mm->mmap_sem); - - if (ret != page_list->nr_pages) - goto unpin; - - local_list->nr_iovecs = i + 1; - } - - return local_list; - -unpin: - dma_unpin_iovec_pages(local_list); -out: - return NULL; -} - -void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list) -{ - int i, j; - - if (!pinned_list) - return; - - for (i = 0; i < pinned_list->nr_iovecs; i++) { - struct dma_page_list *page_list = &pinned_list->page_list[i]; - for (j = 0; j < page_list->nr_pages; j++) { - set_page_dirty_lock(page_list->pages[j]); - page_cache_release(page_list->pages[j]); - } - } - - kfree(pinned_list); -} - - -/* - * We have already pinned down the pages we will be using in the iovecs. - * Each entry in iov array has corresponding entry in pinned_list->page_list. - * Using array indexing to keep iov[] and page_list[] in sync. - * Initial elements in iov array's iov->iov_len will be 0 if already copied into - * by another call. - * iov array length remaining guaranteed to be bigger than len. - */ -dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov, - struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len) -{ - int iov_byte_offset; - int copy; - dma_cookie_t dma_cookie = 0; - int iovec_idx; - int page_idx; - - if (!chan) - return memcpy_toiovec(iov, kdata, len); - - iovec_idx = 0; - while (iovec_idx < pinned_list->nr_iovecs) { - struct dma_page_list *page_list; - - /* skip already used-up iovecs */ - while (!iov[iovec_idx].iov_len) - iovec_idx++; - - page_list = &pinned_list->page_list[iovec_idx]; - - iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK); - page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK) - - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT; - - /* break up copies to not cross page boundary */ - while (iov[iovec_idx].iov_len) { - copy = min_t(int, PAGE_SIZE - iov_byte_offset, len); - copy = min_t(int, copy, iov[iovec_idx].iov_len); - - dma_cookie = dma_async_memcpy_buf_to_pg(chan, - page_list->pages[page_idx], - iov_byte_offset, - kdata, - copy); - /* poll for a descriptor slot */ - if (unlikely(dma_cookie < 0)) { - dma_async_issue_pending(chan); - continue; - } - - len -= copy; - iov[iovec_idx].iov_len -= copy; - iov[iovec_idx].iov_base += copy; - - if (!len) - return dma_cookie; - - kdata += copy; - iov_byte_offset = 0; - page_idx++; - } - iovec_idx++; - } - - /* really bad if we ever run out of iovecs */ - BUG(); - return -EFAULT; -} - -dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov, - struct dma_pinned_list *pinned_list, struct page *page, - unsigned int offset, size_t len) -{ - int iov_byte_offset; - int copy; - dma_cookie_t dma_cookie = 0; - int iovec_idx; - int page_idx; - int err; - - /* this needs as-yet-unimplemented buf-to-buff, so punt. */ - /* TODO: use dma for this */ - if (!chan || !pinned_list) { - u8 *vaddr = kmap(page); - err = memcpy_toiovec(iov, vaddr + offset, len); - kunmap(page); - return err; - } - - iovec_idx = 0; - while (iovec_idx < pinned_list->nr_iovecs) { - struct dma_page_list *page_list; - - /* skip already used-up iovecs */ - while (!iov[iovec_idx].iov_len) - iovec_idx++; - - page_list = &pinned_list->page_list[iovec_idx]; - - iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK); - page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK) - - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT; - - /* break up copies to not cross page boundary */ - while (iov[iovec_idx].iov_len) { - copy = min_t(int, PAGE_SIZE - iov_byte_offset, len); - copy = min_t(int, copy, iov[iovec_idx].iov_len); - - dma_cookie = dma_async_memcpy_pg_to_pg(chan, - page_list->pages[page_idx], - iov_byte_offset, - page, - offset, - copy); - /* poll for a descriptor slot */ - if (unlikely(dma_cookie < 0)) { - dma_async_issue_pending(chan); - continue; - } - - len -= copy; - iov[iovec_idx].iov_len -= copy; - iov[iovec_idx].iov_base += copy; - - if (!len) - return dma_cookie; - - offset += copy; - iov_byte_offset = 0; - page_idx++; - } - iovec_idx++; - } - - /* really bad if we ever run out of iovecs */ - BUG(); - return -EFAULT; -} diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 394cbc5c93e3..7938272f2edf 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -310,7 +310,8 @@ mv_xor_clean_slot(struct mv_xor_desc_slot *desc, return 0; } -static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan) +/* This function must be called with the mv_xor_chan spinlock held */ +static void mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan) { struct mv_xor_desc_slot *iter, *_iter; dma_cookie_t cookie = 0; @@ -366,18 +367,13 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan) mv_chan->dmachan.completed_cookie = cookie; } -static void -mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan) -{ - spin_lock_bh(&mv_chan->lock); - __mv_xor_slot_cleanup(mv_chan); - spin_unlock_bh(&mv_chan->lock); -} - static void mv_xor_tasklet(unsigned long data) { struct mv_xor_chan *chan = (struct mv_xor_chan *) data; + + spin_lock_bh(&chan->lock); mv_xor_slot_cleanup(chan); + spin_unlock_bh(&chan->lock); } static struct mv_xor_desc_slot * @@ -656,9 +652,10 @@ static void mv_xor_free_chan_resources(struct dma_chan *chan) struct mv_xor_desc_slot *iter, *_iter; int in_use_descs = 0; + spin_lock_bh(&mv_chan->lock); + mv_xor_slot_cleanup(mv_chan); - spin_lock_bh(&mv_chan->lock); list_for_each_entry_safe(iter, _iter, &mv_chan->chain, chain_node) { in_use_descs++; @@ -700,11 +697,12 @@ static enum dma_status mv_xor_status(struct dma_chan *chan, enum dma_status ret; ret = dma_cookie_status(chan, cookie, txstate); - if (ret == DMA_COMPLETE) { - mv_xor_clean_completed_slots(mv_chan); + if (ret == DMA_COMPLETE) return ret; - } + + spin_lock_bh(&mv_chan->lock); mv_xor_slot_cleanup(mv_chan); + spin_unlock_bh(&mv_chan->lock); return dma_cookie_status(chan, cookie, txstate); } @@ -782,7 +780,7 @@ static void mv_xor_issue_pending(struct dma_chan *chan) static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan) { - int i; + int i, ret; void *src, *dest; dma_addr_t src_dma, dest_dma; struct dma_chan *dma_chan; @@ -819,19 +817,44 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan) src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src), 0, PAGE_SIZE, DMA_TO_DEVICE); - unmap->to_cnt = 1; unmap->addr[0] = src_dma; + ret = dma_mapping_error(dma_chan->device->dev, src_dma); + if (ret) { + err = -ENOMEM; + goto free_resources; + } + unmap->to_cnt = 1; + dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest), 0, PAGE_SIZE, DMA_FROM_DEVICE); - unmap->from_cnt = 1; unmap->addr[1] = dest_dma; + ret = dma_mapping_error(dma_chan->device->dev, dest_dma); + if (ret) { + err = -ENOMEM; + goto free_resources; + } + unmap->from_cnt = 1; unmap->len = PAGE_SIZE; tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma, PAGE_SIZE, 0); + if (!tx) { + dev_err(dma_chan->device->dev, + "Self-test cannot prepare operation, disabling\n"); + err = -ENODEV; + goto free_resources; + } + cookie = mv_xor_tx_submit(tx); + if (dma_submit_error(cookie)) { + dev_err(dma_chan->device->dev, + "Self-test submit error, disabling\n"); + err = -ENODEV; + goto free_resources; + } + mv_xor_issue_pending(dma_chan); async_tx_ack(tx); msleep(1); @@ -866,7 +889,7 @@ out: static int mv_xor_xor_self_test(struct mv_xor_chan *mv_chan) { - int i, src_idx; + int i, src_idx, ret; struct page *dest; struct page *xor_srcs[MV_XOR_NUM_SRC_TEST]; dma_addr_t dma_srcs[MV_XOR_NUM_SRC_TEST]; @@ -929,19 +952,42 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan) unmap->addr[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i], 0, PAGE_SIZE, DMA_TO_DEVICE); dma_srcs[i] = unmap->addr[i]; + ret = dma_mapping_error(dma_chan->device->dev, unmap->addr[i]); + if (ret) { + err = -ENOMEM; + goto free_resources; + } unmap->to_cnt++; } unmap->addr[src_count] = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE, DMA_FROM_DEVICE); dest_dma = unmap->addr[src_count]; + ret = dma_mapping_error(dma_chan->device->dev, unmap->addr[src_count]); + if (ret) { + err = -ENOMEM; + goto free_resources; + } unmap->from_cnt = 1; unmap->len = PAGE_SIZE; tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs, src_count, PAGE_SIZE, 0); + if (!tx) { + dev_err(dma_chan->device->dev, + "Self-test cannot prepare operation, disabling\n"); + err = -ENODEV; + goto free_resources; + } cookie = mv_xor_tx_submit(tx); + if (dma_submit_error(cookie)) { + dev_err(dma_chan->device->dev, + "Self-test submit error, disabling\n"); + err = -ENODEV; + goto free_resources; + } + mv_xor_issue_pending(dma_chan); async_tx_ack(tx); msleep(8); diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index f8bf00010d45..bbd65149cdb2 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -87,61 +87,73 @@ int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset, } /* + * Select DCT to which PCI cfg accesses are routed + */ +static void f15h_select_dct(struct amd64_pvt *pvt, u8 dct) +{ + u32 reg = 0; + + amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, ®); + reg &= (pvt->model == 0x30) ? ~3 : ~1; + reg |= dct; + amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg); +} + +/* * * Depending on the family, F2 DCT reads need special handling: * - * K8: has a single DCT only + * K8: has a single DCT only and no address offsets >= 0x100 * * F10h: each DCT has its own set of regs * DCT0 -> F2x040.. * DCT1 -> F2x140.. * - * F15h: we select which DCT we access using F1x10C[DctCfgSel] - * * F16h: has only 1 DCT + * + * F15h: we select which DCT we access using F1x10C[DctCfgSel] */ -static int k8_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, - const char *func) +static inline int amd64_read_dct_pci_cfg(struct amd64_pvt *pvt, u8 dct, + int offset, u32 *val) { - if (addr >= 0x100) - return -EINVAL; - - return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func); -} + switch (pvt->fam) { + case 0xf: + if (dct || offset >= 0x100) + return -EINVAL; + break; -static int f10_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, - const char *func) -{ - return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func); -} + case 0x10: + if (dct) { + /* + * Note: If ganging is enabled, barring the regs + * F2x[1,0]98 and F2x[1,0]9C; reads reads to F2x1xx + * return 0. (cf. Section 2.8.1 F10h BKDG) + */ + if (dct_ganging_enabled(pvt)) + return 0; -/* - * Select DCT to which PCI cfg accesses are routed - */ -static void f15h_select_dct(struct amd64_pvt *pvt, u8 dct) -{ - u32 reg = 0; + offset += 0x100; + } + break; - amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, ®); - reg &= (pvt->model >= 0x30) ? ~3 : ~1; - reg |= dct; - amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg); -} + case 0x15: + /* + * F15h: F2x1xx addresses do not map explicitly to DCT1. + * We should select which DCT we access using F1x10C[DctCfgSel] + */ + dct = (dct && pvt->model == 0x30) ? 3 : dct; + f15h_select_dct(pvt, dct); + break; -static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, - const char *func) -{ - u8 dct = 0; + case 0x16: + if (dct) + return -EINVAL; + break; - /* For F15 M30h, the second dct is DCT 3, refer to BKDG Section 2.10 */ - if (addr >= 0x140 && addr <= 0x1a0) { - dct = (pvt->model >= 0x30) ? 3 : 1; - addr -= 0x100; + default: + break; } - - f15h_select_dct(pvt, dct); - - return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func); + return amd64_read_pci_cfg(pvt->F2, offset, val); } /* @@ -768,16 +780,17 @@ static void read_dct_base_mask(struct amd64_pvt *pvt) u32 *base0 = &pvt->csels[0].csbases[cs]; u32 *base1 = &pvt->csels[1].csbases[cs]; - if (!amd64_read_dct_pci_cfg(pvt, reg0, base0)) + if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0)) edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n", cs, *base0, reg0); - if (pvt->fam == 0xf || dct_ganging_enabled(pvt)) + if (pvt->fam == 0xf) continue; - if (!amd64_read_dct_pci_cfg(pvt, reg1, base1)) + if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1)) edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n", - cs, *base1, reg1); + cs, *base1, (pvt->fam == 0x10) ? reg1 + : reg0); } for_each_chip_select_mask(cs, 0, pvt) { @@ -786,16 +799,17 @@ static void read_dct_base_mask(struct amd64_pvt *pvt) u32 *mask0 = &pvt->csels[0].csmasks[cs]; u32 *mask1 = &pvt->csels[1].csmasks[cs]; - if (!amd64_read_dct_pci_cfg(pvt, reg0, mask0)) + if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0)) edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n", cs, *mask0, reg0); - if (pvt->fam == 0xf || dct_ganging_enabled(pvt)) + if (pvt->fam == 0xf) continue; - if (!amd64_read_dct_pci_cfg(pvt, reg1, mask1)) + if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1)) edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n", - cs, *mask1, reg1); + cs, *mask1, (pvt->fam == 0x10) ? reg1 + : reg0); } } @@ -1198,7 +1212,7 @@ static void read_dram_ctl_register(struct amd64_pvt *pvt) if (pvt->fam == 0xf) return; - if (!amd64_read_dct_pci_cfg(pvt, DCT_SEL_LO, &pvt->dct_sel_lo)) { + if (!amd64_read_pci_cfg(pvt->F2, DCT_SEL_LO, &pvt->dct_sel_lo)) { edac_dbg(0, "F2x110 (DCTSelLow): 0x%08x, High range addrs at: 0x%x\n", pvt->dct_sel_lo, dct_sel_baseaddr(pvt)); @@ -1219,7 +1233,7 @@ static void read_dram_ctl_register(struct amd64_pvt *pvt) dct_sel_interleave_addr(pvt)); } - amd64_read_dct_pci_cfg(pvt, DCT_SEL_HI, &pvt->dct_sel_hi); + amd64_read_pci_cfg(pvt->F2, DCT_SEL_HI, &pvt->dct_sel_hi); } /* @@ -1430,7 +1444,7 @@ static u64 f1x_swap_interleaved_region(struct amd64_pvt *pvt, u64 sys_addr) return sys_addr; } - amd64_read_dct_pci_cfg(pvt, SWAP_INTLV_REG, &swap_reg); + amd64_read_pci_cfg(pvt->F2, SWAP_INTLV_REG, &swap_reg); if (!(swap_reg & 0x1)) return sys_addr; @@ -1723,10 +1737,16 @@ static void debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) WARN_ON(ctrl != 0); } - dbam = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->dbam1 : pvt->dbam0; - dcsb = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->csels[1].csbases - : pvt->csels[0].csbases; - + if (pvt->fam == 0x10) { + dbam = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->dbam1 + : pvt->dbam0; + dcsb = (ctrl && !dct_ganging_enabled(pvt)) ? + pvt->csels[1].csbases : + pvt->csels[0].csbases; + } else if (ctrl) { + dbam = pvt->dbam0; + dcsb = pvt->csels[1].csbases; + } edac_dbg(1, "F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n", ctrl, dbam); @@ -1760,7 +1780,6 @@ static struct amd64_family_type family_types[] = { .early_channel_count = k8_early_channel_count, .map_sysaddr_to_csrow = k8_map_sysaddr_to_csrow, .dbam_to_cs = k8_dbam_to_chip_select, - .read_dct_pci_cfg = k8_read_dct_pci_cfg, } }, [F10_CPUS] = { @@ -1771,7 +1790,6 @@ static struct amd64_family_type family_types[] = { .early_channel_count = f1x_early_channel_count, .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, .dbam_to_cs = f10_dbam_to_chip_select, - .read_dct_pci_cfg = f10_read_dct_pci_cfg, } }, [F15_CPUS] = { @@ -1782,7 +1800,6 @@ static struct amd64_family_type family_types[] = { .early_channel_count = f1x_early_channel_count, .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, .dbam_to_cs = f15_dbam_to_chip_select, - .read_dct_pci_cfg = f15_read_dct_pci_cfg, } }, [F15_M30H_CPUS] = { @@ -1793,7 +1810,6 @@ static struct amd64_family_type family_types[] = { .early_channel_count = f1x_early_channel_count, .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, .dbam_to_cs = f16_dbam_to_chip_select, - .read_dct_pci_cfg = f15_read_dct_pci_cfg, } }, [F16_CPUS] = { @@ -1804,7 +1820,6 @@ static struct amd64_family_type family_types[] = { .early_channel_count = f1x_early_channel_count, .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, .dbam_to_cs = f16_dbam_to_chip_select, - .read_dct_pci_cfg = f10_read_dct_pci_cfg, } }, [F16_M30H_CPUS] = { @@ -1815,7 +1830,6 @@ static struct amd64_family_type family_types[] = { .early_channel_count = f1x_early_channel_count, .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, .dbam_to_cs = f16_dbam_to_chip_select, - .read_dct_pci_cfg = f10_read_dct_pci_cfg, } }, }; @@ -2148,25 +2162,25 @@ static void read_mc_regs(struct amd64_pvt *pvt) read_dct_base_mask(pvt); amd64_read_pci_cfg(pvt->F1, DHAR, &pvt->dhar); - amd64_read_dct_pci_cfg(pvt, DBAM0, &pvt->dbam0); + amd64_read_dct_pci_cfg(pvt, 0, DBAM0, &pvt->dbam0); amd64_read_pci_cfg(pvt->F3, F10_ONLINE_SPARE, &pvt->online_spare); - amd64_read_dct_pci_cfg(pvt, DCLR0, &pvt->dclr0); - amd64_read_dct_pci_cfg(pvt, DCHR0, &pvt->dchr0); + amd64_read_dct_pci_cfg(pvt, 0, DCLR0, &pvt->dclr0); + amd64_read_dct_pci_cfg(pvt, 0, DCHR0, &pvt->dchr0); if (!dct_ganging_enabled(pvt)) { - amd64_read_dct_pci_cfg(pvt, DCLR1, &pvt->dclr1); - amd64_read_dct_pci_cfg(pvt, DCHR1, &pvt->dchr1); + amd64_read_dct_pci_cfg(pvt, 1, DCLR0, &pvt->dclr1); + amd64_read_dct_pci_cfg(pvt, 1, DCHR0, &pvt->dchr1); } pvt->ecc_sym_sz = 4; if (pvt->fam >= 0x10) { amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp); + /* F16h has only DCT0, so no need to read dbam1 */ if (pvt->fam != 0x16) - /* F16h has only DCT0 */ - amd64_read_dct_pci_cfg(pvt, DBAM1, &pvt->dbam1); + amd64_read_dct_pci_cfg(pvt, 1, DBAM0, &pvt->dbam1); /* F10h, revD and later can do x8 ECC too */ if ((pvt->fam > 0x10 || pvt->model > 7) && tmp & BIT(25)) diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index d903e0c21144..55fb5941c6d4 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -481,8 +481,6 @@ struct low_ops { void (*map_sysaddr_to_csrow) (struct mem_ctl_info *mci, u64 sys_addr, struct err_info *); int (*dbam_to_cs) (struct amd64_pvt *pvt, u8 dct, unsigned cs_mode); - int (*read_dct_pci_cfg) (struct amd64_pvt *pvt, int offset, - u32 *val, const char *func); }; struct amd64_family_type { @@ -502,9 +500,6 @@ int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset, #define amd64_write_pci_cfg(pdev, offset, val) \ __amd64_write_pci_cfg_dword(pdev, offset, val, __func__) -#define amd64_read_dct_pci_cfg(pvt, offset, val) \ - pvt->ops->read_dct_pci_cfg(pvt, offset, val, __func__) - int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, u64 *hole_offset, u64 *hole_size); diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 3c2625e7980d..6c9f381e8fe6 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -66,7 +66,7 @@ #define EDAC_PCI "PCI" #define EDAC_DEBUG "DEBUG" -extern const char *edac_mem_types[]; +extern const char * const edac_mem_types[]; #ifdef CONFIG_EDAC_DEBUG extern int edac_debug_level; diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 9f134823fa75..c3893b0ddb18 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -128,7 +128,7 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci) /* * keep those in sync with the enum mem_type */ -const char *edac_mem_types[] = { +const char * const edac_mem_types[] = { "Empty csrow", "Reserved csrow type", "Unknown csrow type", diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index f4aec2e6ef56..7d3742edbaa2 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -633,7 +633,7 @@ static int mpc85xx_l2_err_probe(struct platform_device *op) if (edac_op_state == EDAC_OPSTATE_INT) { pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0); res = devm_request_irq(&op->dev, pdata->irq, - mpc85xx_l2_isr, 0, + mpc85xx_l2_isr, IRQF_SHARED, "[EDAC] L2 err", edac_dev); if (res < 0) { printk(KERN_ERR diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index ef6b7e08f485..0f04d5ead521 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -974,7 +974,7 @@ static int ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) * page size (PAGE_SIZE) or the memory width (2 or 4). */ for (j = 0; j < csi->nr_channels; j++) { - struct dimm_info *dimm = csi->channels[j].dimm; + struct dimm_info *dimm = csi->channels[j]->dimm; dimm->nr_pages = nr_pages / csi->nr_channels; dimm->grain = 1; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1411613f2174..e42925f76b4b 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1310,6 +1310,16 @@ void i915_check_and_clear_faults(struct drm_device *dev) POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS])); } +static void i915_ggtt_flush(struct drm_i915_private *dev_priv) +{ + if (INTEL_INFO(dev_priv->dev)->gen < 6) { + intel_gtt_chipset_flush(); + } else { + I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); + POSTING_READ(GFX_FLSH_CNTL_GEN6); + } +} + void i915_gem_suspend_gtt_mappings(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1326,6 +1336,8 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) dev_priv->gtt.base.start, dev_priv->gtt.base.total, true); + + i915_ggtt_flush(dev_priv); } void i915_gem_restore_gtt_mappings(struct drm_device *dev) @@ -1378,7 +1390,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) gen6_write_pdes(container_of(vm, struct i915_hw_ppgtt, base)); } - i915_gem_chipset_flush(dev); + i915_ggtt_flush(dev_priv); } int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 7f84dd263ee8..9842fd2e742a 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -66,12 +66,12 @@ module_param_named(powersave, i915.powersave, int, 0600); MODULE_PARM_DESC(powersave, "Enable powersavings, fbc, downclocking, etc. (default: true)"); -module_param_named(semaphores, i915.semaphores, int, 0400); +module_param_named_unsafe(semaphores, i915.semaphores, int, 0400); MODULE_PARM_DESC(semaphores, "Use semaphores for inter-ring sync " "(default: -1 (use per-chip defaults))"); -module_param_named(enable_rc6, i915.enable_rc6, int, 0400); +module_param_named_unsafe(enable_rc6, i915.enable_rc6, int, 0400); MODULE_PARM_DESC(enable_rc6, "Enable power-saving render C-state 6. " "Different stages can be selected via bitmask values " @@ -79,7 +79,7 @@ MODULE_PARM_DESC(enable_rc6, "For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. " "default: -1 (use per-chip default)"); -module_param_named(enable_fbc, i915.enable_fbc, int, 0600); +module_param_named_unsafe(enable_fbc, i915.enable_fbc, int, 0600); MODULE_PARM_DESC(enable_fbc, "Enable frame buffer compression for power savings " "(default: -1 (use per-chip default))"); @@ -113,7 +113,7 @@ MODULE_PARM_DESC(enable_hangcheck, "WARNING: Disabling this can cause system wide hangs. " "(default: true)"); -module_param_named(enable_ppgtt, i915.enable_ppgtt, int, 0400); +module_param_named_unsafe(enable_ppgtt, i915.enable_ppgtt, int, 0400); MODULE_PARM_DESC(enable_ppgtt, "Override PPGTT usage. " "(-1=auto [default], 0=disabled, 1=aliasing, 2=full)"); diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index ca52ad2ae7d1..d8de1d5140a7 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -396,6 +396,16 @@ int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state) return -EINVAL; } +/* + * If the vendor backlight interface is not in use and ACPI backlight interface + * is broken, do not bother processing backlight change requests from firmware. + */ +static bool should_ignore_backlight_request(void) +{ + return acpi_video_backlight_support() && + !acpi_video_verify_backlight_support(); +} + static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -404,11 +414,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp); - /* - * If the acpi_video interface is not supposed to be used, don't - * bother processing backlight level change requests from firmware. - */ - if (!acpi_video_verify_backlight_support()) { + if (should_ignore_backlight_request()) { DRM_DEBUG_KMS("opregion backlight request ignored\n"); return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 4b5bb5d58a54..f8cbb512132f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -1763,9 +1763,10 @@ nv50_disp_intr_unk40_0_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp const int or = ffs(outp->or) - 1; const u32 loff = (or * 0x800) + (link * 0x80); const u16 mask = (outp->sorconf.link << 6) | outp->or; + struct dcb_output match; u8 ver, hdr; - if (dcb_outp_match(bios, DCB_OUTPUT_DP, mask, &ver, &hdr, outp)) + if (dcb_outp_match(bios, DCB_OUTPUT_DP, mask, &ver, &hdr, &match)) nv_mask(priv, 0x61c10c + loff, 0x00000001, 0x00000000); } diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 99cd9e4a2aa6..3440fc999f2f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -285,6 +285,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) struct nouveau_software_chan *swch; struct nv_dma_v0 args = {}; int ret, i; + bool save; nvif_object_map(chan->object); @@ -386,7 +387,11 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) } /* initialise synchronisation */ - return nouveau_fence(chan->drm)->context_new(chan); + save = cli->base.super; + cli->base.super = true; /* hack until fencenv50 fixed */ + ret = nouveau_fence(chan->drm)->context_new(chan); + cli->base.super = save; + return ret; } int diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 65b4fd53dd4e..4a21b2b06ce2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -550,14 +550,12 @@ nouveau_display_destroy(struct drm_device *dev) } int -nouveau_display_suspend(struct drm_device *dev) +nouveau_display_suspend(struct drm_device *dev, bool runtime) { - struct nouveau_drm *drm = nouveau_drm(dev); struct drm_crtc *crtc; nouveau_display_fini(dev); - NV_INFO(drm, "unpinning framebuffer(s)...\n"); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_framebuffer *nouveau_fb; @@ -579,12 +577,13 @@ nouveau_display_suspend(struct drm_device *dev) } void -nouveau_display_repin(struct drm_device *dev) +nouveau_display_resume(struct drm_device *dev, bool runtime) { struct nouveau_drm *drm = nouveau_drm(dev); struct drm_crtc *crtc; - int ret; + int ret, head; + /* re-pin fb/cursors */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_framebuffer *nouveau_fb; @@ -606,13 +605,6 @@ nouveau_display_repin(struct drm_device *dev) if (ret) NV_ERROR(drm, "Could not pin/map cursor.\n"); } -} - -void -nouveau_display_resume(struct drm_device *dev) -{ - struct drm_crtc *crtc; - int head; nouveau_display_init(dev); @@ -627,6 +619,13 @@ nouveau_display_resume(struct drm_device *dev) for (head = 0; head < dev->mode_config.num_crtc; head++) drm_vblank_on(dev, head); + /* This should ensure we don't hit a locking problem when someone + * wakes us up via a connector. We should never go into suspend + * while the display is on anyways. + */ + if (runtime) + return; + drm_helper_resume_force_mode(dev); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 88ca177cb1c7..be3d5947c6be 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -63,9 +63,8 @@ int nouveau_display_create(struct drm_device *dev); void nouveau_display_destroy(struct drm_device *dev); int nouveau_display_init(struct drm_device *dev); void nouveau_display_fini(struct drm_device *dev); -int nouveau_display_suspend(struct drm_device *dev); -void nouveau_display_repin(struct drm_device *dev); -void nouveau_display_resume(struct drm_device *dev); +int nouveau_display_suspend(struct drm_device *dev, bool runtime); +void nouveau_display_resume(struct drm_device *dev, bool runtime); int nouveau_display_vblank_enable(struct drm_device *, int); void nouveau_display_vblank_disable(struct drm_device *, int); int nouveau_display_scanoutpos(struct drm_device *, int, unsigned int, diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 9c3af96a7153..3ed32dd90303 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -547,9 +547,11 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime) struct nouveau_cli *cli; int ret; - if (dev->mode_config.num_crtc && !runtime) { + if (dev->mode_config.num_crtc) { + NV_INFO(drm, "suspending console...\n"); + nouveau_fbcon_set_suspend(dev, 1); NV_INFO(drm, "suspending display...\n"); - ret = nouveau_display_suspend(dev); + ret = nouveau_display_suspend(dev, runtime); if (ret) return ret; } @@ -603,7 +605,7 @@ fail_client: fail_display: if (dev->mode_config.num_crtc) { NV_INFO(drm, "resuming display...\n"); - nouveau_display_resume(dev); + nouveau_display_resume(dev, runtime); } return ret; } @@ -618,9 +620,6 @@ int nouveau_pmops_suspend(struct device *dev) drm_dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) return 0; - if (drm_dev->mode_config.num_crtc) - nouveau_fbcon_set_suspend(drm_dev, 1); - ret = nouveau_do_suspend(drm_dev, false); if (ret) return ret; @@ -633,7 +632,7 @@ int nouveau_pmops_suspend(struct device *dev) } static int -nouveau_do_resume(struct drm_device *dev) +nouveau_do_resume(struct drm_device *dev, bool runtime) { struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_cli *cli; @@ -658,7 +657,9 @@ nouveau_do_resume(struct drm_device *dev) if (dev->mode_config.num_crtc) { NV_INFO(drm, "resuming display...\n"); - nouveau_display_repin(dev); + nouveau_display_resume(dev, runtime); + NV_INFO(drm, "resuming console...\n"); + nouveau_fbcon_set_suspend(dev, 0); } return 0; @@ -681,47 +682,21 @@ int nouveau_pmops_resume(struct device *dev) return ret; pci_set_master(pdev); - ret = nouveau_do_resume(drm_dev); - if (ret) - return ret; - - if (drm_dev->mode_config.num_crtc) { - nouveau_display_resume(drm_dev); - nouveau_fbcon_set_suspend(drm_dev, 0); - } - - return 0; + return nouveau_do_resume(drm_dev, false); } static int nouveau_pmops_freeze(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - int ret; - - if (drm_dev->mode_config.num_crtc) - nouveau_fbcon_set_suspend(drm_dev, 1); - - ret = nouveau_do_suspend(drm_dev, false); - return ret; + return nouveau_do_suspend(drm_dev, false); } static int nouveau_pmops_thaw(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - int ret; - - ret = nouveau_do_resume(drm_dev); - if (ret) - return ret; - - if (drm_dev->mode_config.num_crtc) { - nouveau_display_resume(drm_dev); - nouveau_fbcon_set_suspend(drm_dev, 0); - } - - return 0; + return nouveau_do_resume(drm_dev, false); } @@ -977,7 +952,7 @@ static int nouveau_pmops_runtime_resume(struct device *dev) return ret; pci_set_master(pdev); - ret = nouveau_do_resume(drm_dev); + ret = nouveau_do_resume(drm_dev, true); drm_kms_helper_poll_enable(drm_dev); /* do magic */ nvif_mask(device, 0x88488, (1 << 25), (1 << 25)); diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 8bdd27091db8..49fe6075cc7c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -486,6 +486,16 @@ static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { .fb_probe = nouveau_fbcon_create, }; +static void +nouveau_fbcon_set_suspend_work(struct work_struct *work) +{ + struct nouveau_fbdev *fbcon = container_of(work, typeof(*fbcon), work); + console_lock(); + nouveau_fbcon_accel_restore(fbcon->dev); + nouveau_fbcon_zfill(fbcon->dev, fbcon); + fb_set_suspend(fbcon->helper.fbdev, FBINFO_STATE_RUNNING); + console_unlock(); +} int nouveau_fbcon_init(struct drm_device *dev) @@ -503,6 +513,7 @@ nouveau_fbcon_init(struct drm_device *dev) if (!fbcon) return -ENOMEM; + INIT_WORK(&fbcon->work, nouveau_fbcon_set_suspend_work); fbcon->dev = dev; drm->fbcon = fbcon; @@ -551,14 +562,14 @@ nouveau_fbcon_set_suspend(struct drm_device *dev, int state) { struct nouveau_drm *drm = nouveau_drm(dev); if (drm->fbcon) { - console_lock(); - if (state == 0) { - nouveau_fbcon_accel_restore(dev); - nouveau_fbcon_zfill(dev, drm->fbcon); + if (state == FBINFO_STATE_RUNNING) { + schedule_work(&drm->fbcon->work); + return; } + flush_work(&drm->fbcon->work); + console_lock(); fb_set_suspend(drm->fbcon->helper.fbdev, state); - if (state == 1) - nouveau_fbcon_accel_save_disable(dev); + nouveau_fbcon_accel_save_disable(dev); console_unlock(); } } diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h index 34658cfa8f5d..0b465c7d3907 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h @@ -36,6 +36,7 @@ struct nouveau_fbdev { struct nouveau_framebuffer nouveau_fb; struct list_head fbdev_list; struct drm_device *dev; + struct work_struct work; unsigned int saved_flags; struct nvif_object surf2d; struct nvif_object clip; diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 3a4d64e1dfb1..092d89bd3224 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -674,16 +674,20 @@ static int qup_i2c_probe(struct platform_device *pdev) qup->adap.dev.of_node = pdev->dev.of_node; strlcpy(qup->adap.name, "QUP I2C adapter", sizeof(qup->adap.name)); - ret = i2c_add_adapter(&qup->adap); - if (ret) - goto fail; - pm_runtime_set_autosuspend_delay(qup->dev, MSEC_PER_SEC); pm_runtime_use_autosuspend(qup->dev); pm_runtime_set_active(qup->dev); pm_runtime_enable(qup->dev); + + ret = i2c_add_adapter(&qup->adap); + if (ret) + goto fail_runtime; + return 0; +fail_runtime: + pm_runtime_disable(qup->dev); + pm_runtime_set_suspended(qup->dev); fail: qup_i2c_disable_clocks(qup); return ret; diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index 93cfc837200b..b38b0529946a 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -238,7 +238,7 @@ static void rk3x_i2c_fill_transmit_buf(struct rk3x_i2c *i2c) for (i = 0; i < 8; ++i) { val = 0; for (j = 0; j < 4; ++j) { - if (i2c->processed == i2c->msg->len) + if ((i2c->processed == i2c->msg->len) && (cnt != 0)) break; if (i2c->processed == 0 && cnt == 0) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 183588b11fc1..9f0fbecd1eb5 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -64,6 +64,10 @@ #define cpu_to_group(cpu) cpu_to_node(cpu) #define ANY_GROUP NUMA_NO_NODE +static bool devices_handle_discard_safely = false; +module_param(devices_handle_discard_safely, bool, 0644); +MODULE_PARM_DESC(devices_handle_discard_safely, + "Set to Y if all devices in each array reliably return zeroes on reads from discarded regions"); static struct workqueue_struct *raid5_wq; /* * Stripe cache @@ -6208,7 +6212,7 @@ static int run(struct mddev *mddev) mddev->queue->limits.discard_granularity = stripe; /* * unaligned part of discard request will be ignored, so can't - * guarantee discard_zerors_data + * guarantee discard_zeroes_data */ mddev->queue->limits.discard_zeroes_data = 0; @@ -6233,6 +6237,18 @@ static int run(struct mddev *mddev) !bdev_get_queue(rdev->bdev)-> limits.discard_zeroes_data) discard_supported = false; + /* Unfortunately, discard_zeroes_data is not currently + * a guarantee - just a hint. So we only allow DISCARD + * if the sysadmin has confirmed that only safe devices + * are in use by setting a module parameter. + */ + if (!devices_handle_discard_safely) { + if (discard_supported) { + pr_info("md/raid456: discard support disabled due to uncertainty.\n"); + pr_info("Set raid456.devices_handle_discard_safely=Y to override.\n"); + } + discard_supported = false; + } } if (discard_supported && diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index a7e24848f6c8..9da812b8a786 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3524,6 +3524,7 @@ static struct usb_driver em28xx_usb_driver = { .disconnect = em28xx_usb_disconnect, .suspend = em28xx_usb_suspend, .resume = em28xx_usb_resume, + .reset_resume = em28xx_usb_resume, .id_table = em28xx_id_table, }; diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 2fee73b878c2..823d01c5684c 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -3236,8 +3236,9 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) skb->protocol = eth_type_trans(skb, bp->dev); - if ((len > (bp->dev->mtu + ETH_HLEN)) && - (ntohs(skb->protocol) != 0x8100)) { + if (len > (bp->dev->mtu + ETH_HLEN) && + skb->protocol != htons(0x8100) && + skb->protocol != htons(ETH_P_8021AD)) { dev_kfree_skb(skb); goto next_rx; diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index e7d3a620d96a..ba499489969a 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -6918,7 +6918,8 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) skb->protocol = eth_type_trans(skb, tp->dev); if (len > (tp->dev->mtu + ETH_HLEN) && - skb->protocol != htons(ETH_P_8021Q)) { + skb->protocol != htons(ETH_P_8021Q) && + skb->protocol != htons(ETH_P_8021AD)) { dev_kfree_skb_any(skb); goto drop_it_no_recycle; } diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index ca5d7798b265..e1e02fba4fcc 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -30,7 +30,6 @@ #include <linux/of_device.h> #include <linux/of_mdio.h> #include <linux/of_net.h> -#include <linux/pinctrl/consumer.h> #include "macb.h" @@ -2071,7 +2070,6 @@ static int __init macb_probe(struct platform_device *pdev) struct phy_device *phydev; u32 config; int err = -ENXIO; - struct pinctrl *pinctrl; const char *mac; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -2080,15 +2078,6 @@ static int __init macb_probe(struct platform_device *pdev) goto err_out; } - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) { - err = PTR_ERR(pinctrl); - if (err == -EPROBE_DEFER) - goto err_out; - - dev_warn(&pdev->dev, "No pinctrl provided\n"); - } - err = -ENOMEM; dev = alloc_etherdev(sizeof(*bp)); if (!dev) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 7e2d5d57c598..871e3a5bda38 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -78,13 +78,13 @@ MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero"); #endif /* CONFIG_PCI_MSI */ static uint8_t num_vfs[3] = {0, 0, 0}; -static int num_vfs_argc = 3; +static int num_vfs_argc; module_param_array(num_vfs, byte , &num_vfs_argc, 0444); MODULE_PARM_DESC(num_vfs, "enable #num_vfs functions if num_vfs > 0\n" "num_vfs=port1,port2,port1+2"); static uint8_t probe_vf[3] = {0, 0, 0}; -static int probe_vfs_argc = 3; +static int probe_vfs_argc; module_param_array(probe_vf, byte, &probe_vfs_argc, 0444); MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)\n" "probe_vf=port1,port2,port1+2"); diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index 32058614151a..5c4068353f66 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -135,6 +135,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) int i, j; struct nx_host_tx_ring *tx_ring = adapter->tx_ring; + spin_lock(&adapter->tx_clean_lock); cmd_buf = tx_ring->cmd_buf_arr; for (i = 0; i < tx_ring->num_desc; i++) { buffrag = cmd_buf->frag_array; @@ -158,6 +159,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) } cmd_buf++; } + spin_unlock(&adapter->tx_clean_lock); } void netxen_free_sw_resources(struct netxen_adapter *adapter) @@ -1792,9 +1794,9 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) break; } - if (count && netif_running(netdev)) { - tx_ring->sw_consumer = sw_consumer; + tx_ring->sw_consumer = sw_consumer; + if (count && netif_running(netdev)) { smp_mb(); if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 1159031f885b..5ec5a2b0e989 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1186,7 +1186,6 @@ __netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) return; smp_mb(); - spin_lock(&adapter->tx_clean_lock); netif_carrier_off(netdev); netif_tx_disable(netdev); @@ -1204,7 +1203,6 @@ __netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) netxen_napi_disable(adapter); netxen_release_tx_buffers(adapter); - spin_unlock(&adapter->tx_clean_lock); } /* Usage: During suspend and firmware recovery module */ diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index 86783e1afcf7..3172cdf591fe 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -1177,9 +1177,8 @@ static void qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter) { u32 idc_params, val; - if (qlcnic_83xx_lockless_flash_read32(adapter, - QLC_83XX_IDC_FLASH_PARAM_ADDR, - (u8 *)&idc_params, 1)) { + if (qlcnic_83xx_flash_read32(adapter, QLC_83XX_IDC_FLASH_PARAM_ADDR, + (u8 *)&idc_params, 1)) { dev_info(&adapter->pdev->dev, "%s:failed to get IDC params from flash\n", __func__); adapter->dev_init_timeo = QLC_83XX_IDC_INIT_TIMEOUT_SECS; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 141f116eb868..494e8105adee 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -1333,21 +1333,21 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev, struct qlcnic_host_tx_ring *tx_ring; struct qlcnic_esw_statistics port_stats; struct qlcnic_mac_statistics mac_stats; - int index, ret, length, size, tx_size, ring; + int index, ret, length, size, ring; char *p; - tx_size = adapter->drv_tx_rings * QLCNIC_TX_STATS_LEN; + memset(data, 0, stats->n_stats * sizeof(u64)); - memset(data, 0, tx_size * sizeof(u64)); for (ring = 0, index = 0; ring < adapter->drv_tx_rings; ring++) { - if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { + if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) { tx_ring = &adapter->tx_ring[ring]; data = qlcnic_fill_tx_queue_stats(data, tx_ring); qlcnic_update_stats(adapter); + } else { + data += QLCNIC_TX_STATS_LEN; } } - memset(data, 0, stats->n_stats * sizeof(u64)); length = QLCNIC_STATS_LEN; for (index = 0; index < length; index++) { p = (char *)adapter + qlcnic_gstrings_stats[index].stat_offset; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 6e6ee226de04..b0c1521e08a3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2786,8 +2786,15 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, if (IS_ERR(priv->stmmac_clk)) { dev_warn(priv->device, "%s: warning: cannot get CSR clock\n", __func__); - ret = PTR_ERR(priv->stmmac_clk); - goto error_clk_get; + /* If failed to obtain stmmac_clk and specific clk_csr value + * is NOT passed from the platform, probe fail. + */ + if (!priv->plat->clk_csr) { + ret = PTR_ERR(priv->stmmac_clk); + goto error_clk_get; + } else { + priv->stmmac_clk = NULL; + } } clk_prepare_enable(priv->stmmac_clk); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index a9c5eaadc426..0fcb5e7eb073 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -387,6 +387,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) int hdr_offset; u32 net_trans_info; u32 hash; + u32 skb_length = skb->len; /* We will atmost need two pages to describe the rndis @@ -562,7 +563,7 @@ do_send: drop: if (ret == 0) { - net->stats.tx_bytes += skb->len; + net->stats.tx_bytes += skb_length; net->stats.tx_packets++; } else { kfree(packet); diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 3381c4f91a8c..0c6adaaf898c 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -112,17 +112,15 @@ out: return err; } +/* Requires RTNL */ static int macvtap_set_queue(struct net_device *dev, struct file *file, struct macvtap_queue *q) { struct macvlan_dev *vlan = netdev_priv(dev); - int err = -EBUSY; - rtnl_lock(); if (vlan->numqueues == MAX_MACVTAP_QUEUES) - goto out; + return -EBUSY; - err = 0; rcu_assign_pointer(q->vlan, vlan); rcu_assign_pointer(vlan->taps[vlan->numvtaps], q); sock_hold(&q->sk); @@ -136,9 +134,7 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file, vlan->numvtaps++; vlan->numqueues++; -out: - rtnl_unlock(); - return err; + return 0; } static int macvtap_disable_queue(struct macvtap_queue *q) @@ -454,11 +450,12 @@ static void macvtap_sock_destruct(struct sock *sk) static int macvtap_open(struct inode *inode, struct file *file) { struct net *net = current->nsproxy->net_ns; - struct net_device *dev = dev_get_by_macvtap_minor(iminor(inode)); + struct net_device *dev; struct macvtap_queue *q; - int err; + int err = -ENODEV; - err = -ENODEV; + rtnl_lock(); + dev = dev_get_by_macvtap_minor(iminor(inode)); if (!dev) goto out; @@ -498,6 +495,7 @@ out: if (dev) dev_put(dev); + rtnl_unlock(); return err; } diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 74760e8143e3..604ef210a4de 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -24,7 +24,7 @@ #include <net/ip6_checksum.h> /* Version Information */ -#define DRIVER_VERSION "v1.06.0 (2014/03/03)" +#define DRIVER_VERSION "v1.06.1 (2014/10/01)" #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" #define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters" #define MODULENAME "r8152" @@ -1949,10 +1949,34 @@ static void rxdy_gated_en(struct r8152 *tp, bool enable) ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data); } +static int rtl_start_rx(struct r8152 *tp) +{ + int i, ret = 0; + + INIT_LIST_HEAD(&tp->rx_done); + for (i = 0; i < RTL8152_MAX_RX; i++) { + INIT_LIST_HEAD(&tp->rx_info[i].list); + ret = r8152_submit_rx(tp, &tp->rx_info[i], GFP_KERNEL); + if (ret) + break; + } + + return ret; +} + +static int rtl_stop_rx(struct r8152 *tp) +{ + int i; + + for (i = 0; i < RTL8152_MAX_RX; i++) + usb_kill_urb(tp->rx_info[i].urb); + + return 0; +} + static int rtl_enable(struct r8152 *tp) { u32 ocp_data; - int i, ret; r8152b_reset_packet_filter(tp); @@ -1962,14 +1986,7 @@ static int rtl_enable(struct r8152 *tp) rxdy_gated_en(tp, false); - INIT_LIST_HEAD(&tp->rx_done); - ret = 0; - for (i = 0; i < RTL8152_MAX_RX; i++) { - INIT_LIST_HEAD(&tp->rx_info[i].list); - ret |= r8152_submit_rx(tp, &tp->rx_info[i], GFP_KERNEL); - } - - return ret; + return rtl_start_rx(tp); } static int rtl8152_enable(struct r8152 *tp) @@ -2053,8 +2070,7 @@ static void rtl_disable(struct r8152 *tp) mdelay(1); } - for (i = 0; i < RTL8152_MAX_RX; i++) - usb_kill_urb(tp->rx_info[i].urb); + rtl_stop_rx(tp); rtl8152_nic_reset(tp); } @@ -2185,28 +2201,6 @@ static void rtl_phy_reset(struct r8152 *tp) } } -static void rtl_clear_bp(struct r8152 *tp) -{ - ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_0, 0); - ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_2, 0); - ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_4, 0); - ocp_write_dword(tp, MCU_TYPE_PLA, PLA_BP_6, 0); - ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_0, 0); - ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_2, 0); - ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_4, 0); - ocp_write_dword(tp, MCU_TYPE_USB, USB_BP_6, 0); - mdelay(3); - ocp_write_word(tp, MCU_TYPE_PLA, PLA_BP_BA, 0); - ocp_write_word(tp, MCU_TYPE_USB, USB_BP_BA, 0); -} - -static void r8153_clear_bp(struct r8152 *tp) -{ - ocp_write_byte(tp, MCU_TYPE_PLA, PLA_BP_EN, 0); - ocp_write_byte(tp, MCU_TYPE_USB, USB_BP_EN, 0); - rtl_clear_bp(tp); -} - static void r8153_teredo_off(struct r8152 *tp) { u32 ocp_data; @@ -2249,8 +2243,6 @@ static void r8152b_hw_phy_cfg(struct r8152 *tp) r8152_mdio_write(tp, MII_BMCR, data); } - rtl_clear_bp(tp); - set_bit(PHY_RESET, &tp->flags); } @@ -2401,8 +2393,6 @@ static void r8153_hw_phy_cfg(struct r8152 *tp) r8152_mdio_write(tp, MII_BMCR, data); } - r8153_clear_bp(tp); - if (tp->version == RTL_VER_03) { data = ocp_reg_read(tp, OCP_EEE_CFG); data &= ~CTAP_SHORT_EN; @@ -3083,13 +3073,14 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message) clear_bit(WORK_ENABLE, &tp->flags); usb_kill_urb(tp->intr_urb); cancel_delayed_work_sync(&tp->schedule); + tasklet_disable(&tp->tl); if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { + rtl_stop_rx(tp); rtl_runtime_suspend_enable(tp, true); } else { - tasklet_disable(&tp->tl); tp->rtl_ops.down(tp); - tasklet_enable(&tp->tl); } + tasklet_enable(&tp->tl); } return 0; @@ -3108,17 +3099,18 @@ static int rtl8152_resume(struct usb_interface *intf) if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { rtl_runtime_suspend_enable(tp, false); clear_bit(SELECTIVE_SUSPEND, &tp->flags); + set_bit(WORK_ENABLE, &tp->flags); if (tp->speed & LINK_STATUS) - tp->rtl_ops.disable(tp); + rtl_start_rx(tp); } else { tp->rtl_ops.up(tp); rtl8152_set_speed(tp, AUTONEG_ENABLE, tp->mii.supports_gmii ? SPEED_1000 : SPEED_100, DUPLEX_FULL); + tp->speed = 0; + netif_carrier_off(tp->netdev); + set_bit(WORK_ENABLE, &tp->flags); } - tp->speed = 0; - netif_carrier_off(tp->netdev); - set_bit(WORK_ENABLE, &tp->flags); usb_submit_urb(tp->intr_urb, GFP_KERNEL); } @@ -3405,7 +3397,7 @@ static void rtl8153_unload(struct r8152 *tp) if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; - r8153_power_cut_en(tp, true); + r8153_power_cut_en(tp, false); } static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id) @@ -3558,7 +3550,11 @@ static void rtl8152_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (tp) { - set_bit(RTL8152_UNPLUG, &tp->flags); + struct usb_device *udev = tp->udev; + + if (udev->state == USB_STATE_NOTATTACHED) + set_bit(RTL8152_UNPLUG, &tp->flags); + tasklet_kill(&tp->tl); unregister_netdev(tp->netdev); tp->rtl_ops.unload(tp); diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index a042d065a0c7..8be2096c8423 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -395,7 +395,8 @@ static void __init superio_serial_init(void) serial_port.iotype = UPIO_PORT; serial_port.type = PORT_16550A; serial_port.uartclk = 115200*16; - serial_port.fifosize = 16; + serial_port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE | + UPF_BOOT_AUTOCONF; /* serial port #1 */ serial_port.iobase = sio_dev.sp1_base; diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index bfd2c2e9f6cd..64d06b52f98a 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -97,95 +97,6 @@ config PINCTRL_BCM281XX BCM28145, and BCM28155 SoCs. This driver requires the pinctrl framework. GPIO is provided by a separate GPIO driver. -config PINCTRL_IMX - bool - select PINMUX - select PINCONF - -config PINCTRL_IMX1_CORE - bool - select PINMUX - select PINCONF - -config PINCTRL_IMX1 - bool "IMX1 pinctrl driver" - depends on SOC_IMX1 - select PINCTRL_IMX1_CORE - help - Say Y here to enable the imx1 pinctrl driver - -config PINCTRL_IMX27 - bool "IMX27 pinctrl driver" - depends on SOC_IMX27 - select PINCTRL_IMX1_CORE - help - Say Y here to enable the imx27 pinctrl driver - - -config PINCTRL_IMX25 - bool "IMX25 pinctrl driver" - depends on OF - depends on SOC_IMX25 - select PINCTRL_IMX - help - Say Y here to enable the imx25 pinctrl driver - -config PINCTRL_IMX35 - bool "IMX35 pinctrl driver" - depends on SOC_IMX35 - select PINCTRL_IMX - help - Say Y here to enable the imx35 pinctrl driver - -config PINCTRL_IMX50 - bool "IMX50 pinctrl driver" - depends on SOC_IMX50 - select PINCTRL_IMX - help - Say Y here to enable the imx50 pinctrl driver - -config PINCTRL_IMX51 - bool "IMX51 pinctrl driver" - depends on SOC_IMX51 - select PINCTRL_IMX - help - Say Y here to enable the imx51 pinctrl driver - -config PINCTRL_IMX53 - bool "IMX53 pinctrl driver" - depends on SOC_IMX53 - select PINCTRL_IMX - help - Say Y here to enable the imx53 pinctrl driver - -config PINCTRL_IMX6Q - bool "IMX6Q/DL pinctrl driver" - depends on SOC_IMX6Q - select PINCTRL_IMX - help - Say Y here to enable the imx6q/dl pinctrl driver - -config PINCTRL_IMX6SL - bool "IMX6SL pinctrl driver" - depends on SOC_IMX6SL - select PINCTRL_IMX - help - Say Y here to enable the imx6sl pinctrl driver - -config PINCTRL_IMX6SX - bool "IMX6SX pinctrl driver" - depends on SOC_IMX6SX - select PINCTRL_IMX - help - Say Y here to enable the imx6sx pinctrl driver - -config PINCTRL_VF610 - bool "Freescale Vybrid VF610 pinctrl driver" - 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 @@ -197,19 +108,6 @@ config PINCTRL_FALCON depends on SOC_FALCON depends on PINCTRL_LANTIQ -config PINCTRL_MXS - bool - select PINMUX - select PINCONF - -config PINCTRL_IMX23 - bool - select PINCTRL_MXS - -config PINCTRL_IMX28 - bool - select PINCTRL_MXS - config PINCTRL_ROCKCHIP bool select PINMUX @@ -306,6 +204,7 @@ config PINCTRL_PALMAS TPS65913, TPS80036 etc. source "drivers/pinctrl/berlin/Kconfig" +source "drivers/pinctrl/freescale/Kconfig" source "drivers/pinctrl/mvebu/Kconfig" source "drivers/pinctrl/nomadik/Kconfig" source "drivers/pinctrl/qcom/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 05d227508c95..51f52d32859e 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -17,23 +17,7 @@ obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o -obj-$(CONFIG_PINCTRL_IMX) += pinctrl-imx.o -obj-$(CONFIG_PINCTRL_IMX1_CORE) += pinctrl-imx1-core.o -obj-$(CONFIG_PINCTRL_IMX1) += pinctrl-imx1.o -obj-$(CONFIG_PINCTRL_IMX27) += pinctrl-imx27.o -obj-$(CONFIG_PINCTRL_IMX35) += pinctrl-imx35.o -obj-$(CONFIG_PINCTRL_IMX50) += pinctrl-imx50.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_IMX6SX) += pinctrl-imx6sx.o obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o -obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o -obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o -obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-imx25.o -obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o @@ -52,15 +36,14 @@ obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o -obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o obj-$(CONFIG_ARCH_BERLIN) += berlin/ +obj-y += freescale/ obj-$(CONFIG_PLAT_ORION) += mvebu/ obj-y += nomadik/ obj-$(CONFIG_ARCH_QCOM) += qcom/ -obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ -obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/ -obj-$(CONFIG_SUPERH) += sh-pfc/ +obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/ +obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/ obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_ARCH_VT8500) += vt8500/ diff --git a/drivers/pinctrl/berlin/berlin.c b/drivers/pinctrl/berlin/berlin.c index 86db2235ab00..7f0b0f93242b 100644 --- a/drivers/pinctrl/berlin/berlin.c +++ b/drivers/pinctrl/berlin/berlin.c @@ -99,30 +99,11 @@ static int berlin_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrl_dev, return 0; } -static void berlin_pinctrl_dt_free_map(struct pinctrl_dev *pctrl_dev, - struct pinctrl_map *map, - unsigned nmaps) -{ - int i; - - for (i = 0; i < nmaps; i++) { - if (map[i].type == PIN_MAP_TYPE_MUX_GROUP) { - kfree(map[i].data.mux.group); - - /* a function can be applied to multiple groups */ - if (i == 0) - kfree(map[i].data.mux.function); - } - } - - kfree(map); -} - static const struct pinctrl_ops berlin_pinctrl_ops = { .get_groups_count = &berlin_pinctrl_get_group_count, .get_group_name = &berlin_pinctrl_get_group_name, .dt_node_to_map = &berlin_pinctrl_dt_node_to_map, - .dt_free_map = &berlin_pinctrl_dt_free_map, + .dt_free_map = &pinctrl_utils_dt_free_map, }; static int berlin_pinmux_get_functions_count(struct pinctrl_dev *pctrl_dev) @@ -170,9 +151,9 @@ berlin_pinctrl_find_function_by_name(struct berlin_pinctrl *pctrl, return NULL; } -static int berlin_pinmux_enable(struct pinctrl_dev *pctrl_dev, - unsigned function, - unsigned group) +static int berlin_pinmux_set(struct pinctrl_dev *pctrl_dev, + unsigned function, + unsigned group) { struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); const struct berlin_desc_group *group_desc = pctrl->desc->groups + group; @@ -197,7 +178,7 @@ static const struct pinmux_ops berlin_pinmux_ops = { .get_functions_count = &berlin_pinmux_get_functions_count, .get_function_name = &berlin_pinmux_get_function_name, .get_function_groups = &berlin_pinmux_get_function_groups, - .enable = &berlin_pinmux_enable, + .set_mux = &berlin_pinmux_set, }; static int berlin_pinctrl_add_function(struct berlin_pinctrl *pctrl, diff --git a/drivers/pinctrl/freescale/Kconfig b/drivers/pinctrl/freescale/Kconfig new file mode 100644 index 000000000000..16aac38793fe --- /dev/null +++ b/drivers/pinctrl/freescale/Kconfig @@ -0,0 +1,108 @@ +config PINCTRL_IMX + bool + select PINMUX + select PINCONF + +config PINCTRL_IMX1_CORE + bool + select PINMUX + select PINCONF + +config PINCTRL_IMX1 + bool "IMX1 pinctrl driver" + depends on SOC_IMX1 + select PINCTRL_IMX1_CORE + help + Say Y here to enable the imx1 pinctrl driver + +config PINCTRL_IMX21 + bool "i.MX21 pinctrl driver" + depends on SOC_IMX21 + select PINCTRL_IMX1_CORE + help + Say Y here to enable the i.MX21 pinctrl driver + +config PINCTRL_IMX27 + bool "IMX27 pinctrl driver" + depends on SOC_IMX27 + select PINCTRL_IMX1_CORE + help + Say Y here to enable the imx27 pinctrl driver + + +config PINCTRL_IMX25 + bool "IMX25 pinctrl driver" + depends on OF + depends on SOC_IMX25 + select PINCTRL_IMX + help + Say Y here to enable the imx25 pinctrl driver + +config PINCTRL_IMX35 + bool "IMX35 pinctrl driver" + depends on SOC_IMX35 + select PINCTRL_IMX + help + Say Y here to enable the imx35 pinctrl driver + +config PINCTRL_IMX50 + bool "IMX50 pinctrl driver" + depends on SOC_IMX50 + select PINCTRL_IMX + help + Say Y here to enable the imx50 pinctrl driver + +config PINCTRL_IMX51 + bool "IMX51 pinctrl driver" + depends on SOC_IMX51 + select PINCTRL_IMX + help + Say Y here to enable the imx51 pinctrl driver + +config PINCTRL_IMX53 + bool "IMX53 pinctrl driver" + depends on SOC_IMX53 + select PINCTRL_IMX + help + Say Y here to enable the imx53 pinctrl driver + +config PINCTRL_IMX6Q + bool "IMX6Q/DL pinctrl driver" + depends on SOC_IMX6Q + select PINCTRL_IMX + help + Say Y here to enable the imx6q/dl pinctrl driver + +config PINCTRL_IMX6SL + bool "IMX6SL pinctrl driver" + depends on SOC_IMX6SL + select PINCTRL_IMX + help + Say Y here to enable the imx6sl pinctrl driver + +config PINCTRL_IMX6SX + bool "IMX6SX pinctrl driver" + depends on SOC_IMX6SX + select PINCTRL_IMX + help + Say Y here to enable the imx6sx pinctrl driver + +config PINCTRL_VF610 + bool "Freescale Vybrid VF610 pinctrl driver" + depends on SOC_VF610 + select PINCTRL_IMX + help + Say Y here to enable the Freescale Vybrid VF610 pinctrl driver + +config PINCTRL_MXS + bool + select PINMUX + select PINCONF + +config PINCTRL_IMX23 + bool + select PINCTRL_MXS + +config PINCTRL_IMX28 + bool + select PINCTRL_MXS diff --git a/drivers/pinctrl/freescale/Makefile b/drivers/pinctrl/freescale/Makefile new file mode 100644 index 000000000000..bba73c22f043 --- /dev/null +++ b/drivers/pinctrl/freescale/Makefile @@ -0,0 +1,19 @@ +# Freescale pin control drivers +obj-$(CONFIG_PINCTRL_IMX) += pinctrl-imx.o +obj-$(CONFIG_PINCTRL_IMX1_CORE) += pinctrl-imx1-core.o +obj-$(CONFIG_PINCTRL_IMX1) += pinctrl-imx1.o +obj-$(CONFIG_PINCTRL_IMX21) += pinctrl-imx21.o +obj-$(CONFIG_PINCTRL_IMX27) += pinctrl-imx27.o +obj-$(CONFIG_PINCTRL_IMX35) += pinctrl-imx35.o +obj-$(CONFIG_PINCTRL_IMX50) += pinctrl-imx50.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_IMX6SX) += pinctrl-imx6sx.o +obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o +obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o +obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o +obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-imx25.o +obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c index 946d594a64dd..f2446769247f 100644 --- a/drivers/pinctrl/pinctrl-imx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx.c @@ -24,7 +24,7 @@ #include <linux/pinctrl/pinmux.h> #include <linux/slab.h> -#include "core.h" +#include "../core.h" #include "pinctrl-imx.h" /* The bits in CONFIG cell defined in binding doc*/ @@ -179,8 +179,8 @@ static const struct pinctrl_ops imx_pctrl_ops = { }; -static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group) +static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) { struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); const struct imx_pinctrl_soc_info *info = ipctl->info; @@ -204,7 +204,7 @@ static int imx_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, pin_id = pin->pin; pin_reg = &info->pin_regs[pin_id]; - if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->mux_reg) { + if (pin_reg->mux_reg == -1) { dev_err(ipctl->dev, "Pin(%s) does not support mux function\n", info->pins[pin_id].name); return -EINVAL; @@ -298,7 +298,7 @@ static const struct pinmux_ops imx_pmx_ops = { .get_functions_count = imx_pmx_get_funcs_count, .get_function_name = imx_pmx_get_func_name, .get_function_groups = imx_pmx_get_groups, - .enable = imx_pmx_enable, + .set_mux = imx_pmx_set, }; static int imx_pinconf_get(struct pinctrl_dev *pctldev, @@ -308,7 +308,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 (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->conf_reg) { + if (pin_reg->conf_reg == -1) { dev_err(info->dev, "Pin(%s) does not support config function\n", info->pins[pin_id].name); return -EINVAL; @@ -331,7 +331,7 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev, const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id]; int i; - if (!(info->flags & ZERO_OFFSET_VALID) && !pin_reg->conf_reg) { + if (pin_reg->conf_reg == -1) { dev_err(info->dev, "Pin(%s) does not support config function\n", info->pins[pin_id].name); return -EINVAL; @@ -586,10 +586,11 @@ int imx_pinctrl_probe(struct platform_device *pdev, if (!ipctl) return -ENOMEM; - info->pin_regs = devm_kzalloc(&pdev->dev, sizeof(*info->pin_regs) * + info->pin_regs = devm_kmalloc(&pdev->dev, sizeof(*info->pin_regs) * info->npins, GFP_KERNEL); if (!info->pin_regs) return -ENOMEM; + memset(info->pin_regs, 0xff, sizeof(*info->pin_regs) * info->npins); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ipctl->base = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/pinctrl/pinctrl-imx.h b/drivers/pinctrl/freescale/pinctrl-imx.h index db408b057000..49e55d39f7c8 100644 --- a/drivers/pinctrl/pinctrl-imx.h +++ b/drivers/pinctrl/freescale/pinctrl-imx.h @@ -67,8 +67,8 @@ struct imx_pmx_func { * @conf_reg: config register offset */ struct imx_pin_reg { - u16 mux_reg; - u16 conf_reg; + s16 mux_reg; + s16 conf_reg; }; struct imx_pinctrl_soc_info { @@ -83,8 +83,7 @@ struct imx_pinctrl_soc_info { unsigned int flags; }; -#define ZERO_OFFSET_VALID 0x1 -#define SHARE_MUX_CONF_REG 0x2 +#define SHARE_MUX_CONF_REG 0x1 #define NO_MUX 0x0 #define NO_PAD 0x0 diff --git a/drivers/pinctrl/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c index 483420757c9f..5ac59fbb2440 100644 --- a/drivers/pinctrl/pinctrl-imx1-core.c +++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c @@ -28,7 +28,7 @@ #include <linux/pinctrl/pinmux.h> #include <linux/slab.h> -#include "core.h" +#include "../core.h" #include "pinctrl-imx1.h" struct imx1_pinctrl { @@ -298,8 +298,8 @@ static const struct pinctrl_ops imx1_pctrl_ops = { }; -static int imx1_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group) +static int imx1_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) { struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); const struct imx1_pinctrl_soc_info *info = ipctl->info; @@ -385,7 +385,7 @@ static const struct pinmux_ops imx1_pmx_ops = { .get_functions_count = imx1_pmx_get_funcs_count, .get_function_name = imx1_pmx_get_func_name, .get_function_groups = imx1_pmx_get_groups, - .enable = imx1_pmx_enable, + .set_mux = imx1_pmx_set, }; static int imx1_pinconf_get(struct pinctrl_dev *pctldev, diff --git a/drivers/pinctrl/pinctrl-imx1.c b/drivers/pinctrl/freescale/pinctrl-imx1.c index 533a6e519648..533a6e519648 100644 --- a/drivers/pinctrl/pinctrl-imx1.c +++ b/drivers/pinctrl/freescale/pinctrl-imx1.c diff --git a/drivers/pinctrl/pinctrl-imx1.h b/drivers/pinctrl/freescale/pinctrl-imx1.h index 692a54c15cda..692a54c15cda 100644 --- a/drivers/pinctrl/pinctrl-imx1.h +++ b/drivers/pinctrl/freescale/pinctrl-imx1.h diff --git a/drivers/pinctrl/freescale/pinctrl-imx21.c b/drivers/pinctrl/freescale/pinctrl-imx21.c new file mode 100644 index 000000000000..1b3b2311b033 --- /dev/null +++ b/drivers/pinctrl/freescale/pinctrl-imx21.c @@ -0,0 +1,342 @@ +/* + * i.MX21 pinctrl driver based on imx pinmux core + * + * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru> + * + * 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/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pinctrl/pinctrl.h> + +#include "pinctrl-imx1.h" + +#define PAD_ID(port, pin) ((port) * 32 + (pin)) +#define PA 0 +#define PB 1 +#define PC 2 +#define PD 3 +#define PE 4 +#define PF 5 + +enum imx21_pads { + MX21_PAD_LSCLK = PAD_ID(PA, 5), + MX21_PAD_LD0 = PAD_ID(PA, 6), + MX21_PAD_LD1 = PAD_ID(PA, 7), + MX21_PAD_LD2 = PAD_ID(PA, 8), + MX21_PAD_LD3 = PAD_ID(PA, 9), + MX21_PAD_LD4 = PAD_ID(PA, 10), + MX21_PAD_LD5 = PAD_ID(PA, 11), + MX21_PAD_LD6 = PAD_ID(PA, 12), + MX21_PAD_LD7 = PAD_ID(PA, 13), + MX21_PAD_LD8 = PAD_ID(PA, 14), + MX21_PAD_LD9 = PAD_ID(PA, 15), + MX21_PAD_LD10 = PAD_ID(PA, 16), + MX21_PAD_LD11 = PAD_ID(PA, 17), + MX21_PAD_LD12 = PAD_ID(PA, 18), + MX21_PAD_LD13 = PAD_ID(PA, 19), + MX21_PAD_LD14 = PAD_ID(PA, 20), + MX21_PAD_LD15 = PAD_ID(PA, 21), + MX21_PAD_LD16 = PAD_ID(PA, 22), + MX21_PAD_LD17 = PAD_ID(PA, 23), + MX21_PAD_REV = PAD_ID(PA, 24), + MX21_PAD_CLS = PAD_ID(PA, 25), + MX21_PAD_PS = PAD_ID(PA, 26), + MX21_PAD_SPL_SPR = PAD_ID(PA, 27), + MX21_PAD_HSYNC = PAD_ID(PA, 28), + MX21_PAD_VSYNC = PAD_ID(PA, 29), + MX21_PAD_CONTRAST = PAD_ID(PA, 30), + MX21_PAD_OE_ACD = PAD_ID(PA, 31), + MX21_PAD_SD2_D0 = PAD_ID(PB, 4), + MX21_PAD_SD2_D1 = PAD_ID(PB, 5), + MX21_PAD_SD2_D2 = PAD_ID(PB, 6), + MX21_PAD_SD2_D3 = PAD_ID(PB, 7), + MX21_PAD_SD2_CMD = PAD_ID(PB, 8), + MX21_PAD_SD2_CLK = PAD_ID(PB, 9), + MX21_PAD_CSI_D0 = PAD_ID(PB, 10), + MX21_PAD_CSI_D1 = PAD_ID(PB, 11), + MX21_PAD_CSI_D2 = PAD_ID(PB, 12), + MX21_PAD_CSI_D3 = PAD_ID(PB, 13), + MX21_PAD_CSI_D4 = PAD_ID(PB, 14), + MX21_PAD_CSI_MCLK = PAD_ID(PB, 15), + MX21_PAD_CSI_PIXCLK = PAD_ID(PB, 16), + MX21_PAD_CSI_D5 = PAD_ID(PB, 17), + MX21_PAD_CSI_D6 = PAD_ID(PB, 18), + MX21_PAD_CSI_D7 = PAD_ID(PB, 19), + MX21_PAD_CSI_VSYNC = PAD_ID(PB, 20), + MX21_PAD_CSI_HSYNC = PAD_ID(PB, 21), + MX21_PAD_USB_BYP = PAD_ID(PB, 22), + MX21_PAD_USB_PWR = PAD_ID(PB, 23), + MX21_PAD_USB_OC = PAD_ID(PB, 24), + MX21_PAD_USBH_ON = PAD_ID(PB, 25), + MX21_PAD_USBH1_FS = PAD_ID(PB, 26), + MX21_PAD_USBH1_OE = PAD_ID(PB, 27), + MX21_PAD_USBH1_TXDM = PAD_ID(PB, 28), + MX21_PAD_USBH1_TXDP = PAD_ID(PB, 29), + MX21_PAD_USBH1_RXDM = PAD_ID(PB, 30), + MX21_PAD_USBH1_RXDP = PAD_ID(PB, 31), + MX21_PAD_USBG_SDA = PAD_ID(PC, 5), + MX21_PAD_USBG_SCL = PAD_ID(PC, 6), + MX21_PAD_USBG_ON = PAD_ID(PC, 7), + MX21_PAD_USBG_FS = PAD_ID(PC, 8), + MX21_PAD_USBG_OE = PAD_ID(PC, 9), + MX21_PAD_USBG_TXDM = PAD_ID(PC, 10), + MX21_PAD_USBG_TXDP = PAD_ID(PC, 11), + MX21_PAD_USBG_RXDM = PAD_ID(PC, 12), + MX21_PAD_USBG_RXDP = PAD_ID(PC, 13), + MX21_PAD_TOUT = PAD_ID(PC, 14), + MX21_PAD_TIN = PAD_ID(PC, 15), + MX21_PAD_SAP_FS = PAD_ID(PC, 16), + MX21_PAD_SAP_RXD = PAD_ID(PC, 17), + MX21_PAD_SAP_TXD = PAD_ID(PC, 18), + MX21_PAD_SAP_CLK = PAD_ID(PC, 19), + MX21_PAD_SSI1_FS = PAD_ID(PC, 20), + MX21_PAD_SSI1_RXD = PAD_ID(PC, 21), + MX21_PAD_SSI1_TXD = PAD_ID(PC, 22), + MX21_PAD_SSI1_CLK = PAD_ID(PC, 23), + MX21_PAD_SSI2_FS = PAD_ID(PC, 24), + MX21_PAD_SSI2_RXD = PAD_ID(PC, 25), + MX21_PAD_SSI2_TXD = PAD_ID(PC, 26), + MX21_PAD_SSI2_CLK = PAD_ID(PC, 27), + MX21_PAD_SSI3_FS = PAD_ID(PC, 28), + MX21_PAD_SSI3_RXD = PAD_ID(PC, 29), + MX21_PAD_SSI3_TXD = PAD_ID(PC, 30), + MX21_PAD_SSI3_CLK = PAD_ID(PC, 31), + MX21_PAD_I2C_DATA = PAD_ID(PD, 17), + MX21_PAD_I2C_CLK = PAD_ID(PD, 18), + MX21_PAD_CSPI2_SS2 = PAD_ID(PD, 19), + MX21_PAD_CSPI2_SS1 = PAD_ID(PD, 20), + MX21_PAD_CSPI2_SS0 = PAD_ID(PD, 21), + MX21_PAD_CSPI2_SCLK = PAD_ID(PD, 22), + MX21_PAD_CSPI2_MISO = PAD_ID(PD, 23), + MX21_PAD_CSPI2_MOSI = PAD_ID(PD, 24), + MX21_PAD_CSPI1_RDY = PAD_ID(PD, 25), + MX21_PAD_CSPI1_SS2 = PAD_ID(PD, 26), + MX21_PAD_CSPI1_SS1 = PAD_ID(PD, 27), + MX21_PAD_CSPI1_SS0 = PAD_ID(PD, 28), + MX21_PAD_CSPI1_SCLK = PAD_ID(PD, 29), + MX21_PAD_CSPI1_MISO = PAD_ID(PD, 30), + MX21_PAD_CSPI1_MOSI = PAD_ID(PD, 31), + MX21_PAD_TEST_WB2 = PAD_ID(PE, 0), + MX21_PAD_TEST_WB1 = PAD_ID(PE, 1), + MX21_PAD_TEST_WB0 = PAD_ID(PE, 2), + MX21_PAD_UART2_CTS = PAD_ID(PE, 3), + MX21_PAD_UART2_RTS = PAD_ID(PE, 4), + MX21_PAD_PWMO = PAD_ID(PE, 5), + MX21_PAD_UART2_TXD = PAD_ID(PE, 6), + MX21_PAD_UART2_RXD = PAD_ID(PE, 7), + MX21_PAD_UART3_TXD = PAD_ID(PE, 8), + MX21_PAD_UART3_RXD = PAD_ID(PE, 9), + MX21_PAD_UART3_CTS = PAD_ID(PE, 10), + MX21_PAD_UART3_RTS = PAD_ID(PE, 11), + MX21_PAD_UART1_TXD = PAD_ID(PE, 12), + MX21_PAD_UART1_RXD = PAD_ID(PE, 13), + MX21_PAD_UART1_CTS = PAD_ID(PE, 14), + MX21_PAD_UART1_RTS = PAD_ID(PE, 15), + MX21_PAD_RTCK = PAD_ID(PE, 16), + MX21_PAD_RESET_OUT = PAD_ID(PE, 17), + MX21_PAD_SD1_D0 = PAD_ID(PE, 18), + MX21_PAD_SD1_D1 = PAD_ID(PE, 19), + MX21_PAD_SD1_D2 = PAD_ID(PE, 20), + MX21_PAD_SD1_D3 = PAD_ID(PE, 21), + MX21_PAD_SD1_CMD = PAD_ID(PE, 22), + MX21_PAD_SD1_CLK = PAD_ID(PE, 23), + MX21_PAD_NFRB = PAD_ID(PF, 0), + MX21_PAD_NFCE = PAD_ID(PF, 1), + MX21_PAD_NFWP = PAD_ID(PF, 2), + MX21_PAD_NFCLE = PAD_ID(PF, 3), + MX21_PAD_NFALE = PAD_ID(PF, 4), + MX21_PAD_NFRE = PAD_ID(PF, 5), + MX21_PAD_NFWE = PAD_ID(PF, 6), + MX21_PAD_NFIO0 = PAD_ID(PF, 7), + MX21_PAD_NFIO1 = PAD_ID(PF, 8), + MX21_PAD_NFIO2 = PAD_ID(PF, 9), + MX21_PAD_NFIO3 = PAD_ID(PF, 10), + MX21_PAD_NFIO4 = PAD_ID(PF, 11), + MX21_PAD_NFIO5 = PAD_ID(PF, 12), + MX21_PAD_NFIO6 = PAD_ID(PF, 13), + MX21_PAD_NFIO7 = PAD_ID(PF, 14), + MX21_PAD_CLKO = PAD_ID(PF, 15), + MX21_PAD_RESERVED = PAD_ID(PF, 16), + MX21_PAD_CS4 = PAD_ID(PF, 21), + MX21_PAD_CS5 = PAD_ID(PF, 22), +}; + +/* Pad names for the pinmux subsystem */ +static const struct pinctrl_pin_desc imx21_pinctrl_pads[] = { + IMX_PINCTRL_PIN(MX21_PAD_LSCLK), + IMX_PINCTRL_PIN(MX21_PAD_LD0), + IMX_PINCTRL_PIN(MX21_PAD_LD1), + IMX_PINCTRL_PIN(MX21_PAD_LD2), + IMX_PINCTRL_PIN(MX21_PAD_LD3), + IMX_PINCTRL_PIN(MX21_PAD_LD4), + IMX_PINCTRL_PIN(MX21_PAD_LD5), + IMX_PINCTRL_PIN(MX21_PAD_LD6), + IMX_PINCTRL_PIN(MX21_PAD_LD7), + IMX_PINCTRL_PIN(MX21_PAD_LD8), + IMX_PINCTRL_PIN(MX21_PAD_LD9), + IMX_PINCTRL_PIN(MX21_PAD_LD10), + IMX_PINCTRL_PIN(MX21_PAD_LD11), + IMX_PINCTRL_PIN(MX21_PAD_LD12), + IMX_PINCTRL_PIN(MX21_PAD_LD13), + IMX_PINCTRL_PIN(MX21_PAD_LD14), + IMX_PINCTRL_PIN(MX21_PAD_LD15), + IMX_PINCTRL_PIN(MX21_PAD_LD16), + IMX_PINCTRL_PIN(MX21_PAD_LD17), + IMX_PINCTRL_PIN(MX21_PAD_REV), + IMX_PINCTRL_PIN(MX21_PAD_CLS), + IMX_PINCTRL_PIN(MX21_PAD_PS), + IMX_PINCTRL_PIN(MX21_PAD_SPL_SPR), + IMX_PINCTRL_PIN(MX21_PAD_HSYNC), + IMX_PINCTRL_PIN(MX21_PAD_VSYNC), + IMX_PINCTRL_PIN(MX21_PAD_CONTRAST), + IMX_PINCTRL_PIN(MX21_PAD_OE_ACD), + IMX_PINCTRL_PIN(MX21_PAD_SD2_D0), + IMX_PINCTRL_PIN(MX21_PAD_SD2_D1), + IMX_PINCTRL_PIN(MX21_PAD_SD2_D2), + IMX_PINCTRL_PIN(MX21_PAD_SD2_D3), + IMX_PINCTRL_PIN(MX21_PAD_SD2_CMD), + IMX_PINCTRL_PIN(MX21_PAD_SD2_CLK), + IMX_PINCTRL_PIN(MX21_PAD_CSI_D0), + IMX_PINCTRL_PIN(MX21_PAD_CSI_D1), + IMX_PINCTRL_PIN(MX21_PAD_CSI_D2), + IMX_PINCTRL_PIN(MX21_PAD_CSI_D3), + IMX_PINCTRL_PIN(MX21_PAD_CSI_D4), + IMX_PINCTRL_PIN(MX21_PAD_CSI_MCLK), + IMX_PINCTRL_PIN(MX21_PAD_CSI_PIXCLK), + IMX_PINCTRL_PIN(MX21_PAD_CSI_D5), + IMX_PINCTRL_PIN(MX21_PAD_CSI_D6), + IMX_PINCTRL_PIN(MX21_PAD_CSI_D7), + IMX_PINCTRL_PIN(MX21_PAD_CSI_VSYNC), + IMX_PINCTRL_PIN(MX21_PAD_CSI_HSYNC), + IMX_PINCTRL_PIN(MX21_PAD_USB_BYP), + IMX_PINCTRL_PIN(MX21_PAD_USB_PWR), + IMX_PINCTRL_PIN(MX21_PAD_USB_OC), + IMX_PINCTRL_PIN(MX21_PAD_USBH_ON), + IMX_PINCTRL_PIN(MX21_PAD_USBH1_FS), + IMX_PINCTRL_PIN(MX21_PAD_USBH1_OE), + IMX_PINCTRL_PIN(MX21_PAD_USBH1_TXDM), + IMX_PINCTRL_PIN(MX21_PAD_USBH1_TXDP), + IMX_PINCTRL_PIN(MX21_PAD_USBH1_RXDM), + IMX_PINCTRL_PIN(MX21_PAD_USBH1_RXDP), + IMX_PINCTRL_PIN(MX21_PAD_USBG_SDA), + IMX_PINCTRL_PIN(MX21_PAD_USBG_SCL), + IMX_PINCTRL_PIN(MX21_PAD_USBG_ON), + IMX_PINCTRL_PIN(MX21_PAD_USBG_FS), + IMX_PINCTRL_PIN(MX21_PAD_USBG_OE), + IMX_PINCTRL_PIN(MX21_PAD_USBG_TXDM), + IMX_PINCTRL_PIN(MX21_PAD_USBG_TXDP), + IMX_PINCTRL_PIN(MX21_PAD_USBG_RXDM), + IMX_PINCTRL_PIN(MX21_PAD_USBG_RXDP), + IMX_PINCTRL_PIN(MX21_PAD_TOUT), + IMX_PINCTRL_PIN(MX21_PAD_TIN), + IMX_PINCTRL_PIN(MX21_PAD_SAP_FS), + IMX_PINCTRL_PIN(MX21_PAD_SAP_RXD), + IMX_PINCTRL_PIN(MX21_PAD_SAP_TXD), + IMX_PINCTRL_PIN(MX21_PAD_SAP_CLK), + IMX_PINCTRL_PIN(MX21_PAD_SSI1_FS), + IMX_PINCTRL_PIN(MX21_PAD_SSI1_RXD), + IMX_PINCTRL_PIN(MX21_PAD_SSI1_TXD), + IMX_PINCTRL_PIN(MX21_PAD_SSI1_CLK), + IMX_PINCTRL_PIN(MX21_PAD_SSI2_FS), + IMX_PINCTRL_PIN(MX21_PAD_SSI2_RXD), + IMX_PINCTRL_PIN(MX21_PAD_SSI2_TXD), + IMX_PINCTRL_PIN(MX21_PAD_SSI2_CLK), + IMX_PINCTRL_PIN(MX21_PAD_SSI3_FS), + IMX_PINCTRL_PIN(MX21_PAD_SSI3_RXD), + IMX_PINCTRL_PIN(MX21_PAD_SSI3_TXD), + IMX_PINCTRL_PIN(MX21_PAD_SSI3_CLK), + IMX_PINCTRL_PIN(MX21_PAD_I2C_DATA), + IMX_PINCTRL_PIN(MX21_PAD_I2C_CLK), + IMX_PINCTRL_PIN(MX21_PAD_CSPI2_SS2), + IMX_PINCTRL_PIN(MX21_PAD_CSPI2_SS1), + IMX_PINCTRL_PIN(MX21_PAD_CSPI2_SS0), + IMX_PINCTRL_PIN(MX21_PAD_CSPI2_SCLK), + IMX_PINCTRL_PIN(MX21_PAD_CSPI2_MISO), + IMX_PINCTRL_PIN(MX21_PAD_CSPI2_MOSI), + IMX_PINCTRL_PIN(MX21_PAD_CSPI1_RDY), + IMX_PINCTRL_PIN(MX21_PAD_CSPI1_SS2), + IMX_PINCTRL_PIN(MX21_PAD_CSPI1_SS1), + IMX_PINCTRL_PIN(MX21_PAD_CSPI1_SS0), + IMX_PINCTRL_PIN(MX21_PAD_CSPI1_SCLK), + IMX_PINCTRL_PIN(MX21_PAD_CSPI1_MISO), + IMX_PINCTRL_PIN(MX21_PAD_CSPI1_MOSI), + IMX_PINCTRL_PIN(MX21_PAD_TEST_WB2), + IMX_PINCTRL_PIN(MX21_PAD_TEST_WB1), + IMX_PINCTRL_PIN(MX21_PAD_TEST_WB0), + IMX_PINCTRL_PIN(MX21_PAD_UART2_CTS), + IMX_PINCTRL_PIN(MX21_PAD_UART2_RTS), + IMX_PINCTRL_PIN(MX21_PAD_PWMO), + IMX_PINCTRL_PIN(MX21_PAD_UART2_TXD), + IMX_PINCTRL_PIN(MX21_PAD_UART2_RXD), + IMX_PINCTRL_PIN(MX21_PAD_UART3_TXD), + IMX_PINCTRL_PIN(MX21_PAD_UART3_RXD), + IMX_PINCTRL_PIN(MX21_PAD_UART3_CTS), + IMX_PINCTRL_PIN(MX21_PAD_UART3_RTS), + IMX_PINCTRL_PIN(MX21_PAD_UART1_TXD), + IMX_PINCTRL_PIN(MX21_PAD_UART1_RXD), + IMX_PINCTRL_PIN(MX21_PAD_UART1_CTS), + IMX_PINCTRL_PIN(MX21_PAD_UART1_RTS), + IMX_PINCTRL_PIN(MX21_PAD_RTCK), + IMX_PINCTRL_PIN(MX21_PAD_RESET_OUT), + IMX_PINCTRL_PIN(MX21_PAD_SD1_D0), + IMX_PINCTRL_PIN(MX21_PAD_SD1_D1), + IMX_PINCTRL_PIN(MX21_PAD_SD1_D2), + IMX_PINCTRL_PIN(MX21_PAD_SD1_D3), + IMX_PINCTRL_PIN(MX21_PAD_SD1_CMD), + IMX_PINCTRL_PIN(MX21_PAD_SD1_CLK), + IMX_PINCTRL_PIN(MX21_PAD_NFRB), + IMX_PINCTRL_PIN(MX21_PAD_NFCE), + IMX_PINCTRL_PIN(MX21_PAD_NFWP), + IMX_PINCTRL_PIN(MX21_PAD_NFCLE), + IMX_PINCTRL_PIN(MX21_PAD_NFALE), + IMX_PINCTRL_PIN(MX21_PAD_NFRE), + IMX_PINCTRL_PIN(MX21_PAD_NFWE), + IMX_PINCTRL_PIN(MX21_PAD_NFIO0), + IMX_PINCTRL_PIN(MX21_PAD_NFIO1), + IMX_PINCTRL_PIN(MX21_PAD_NFIO2), + IMX_PINCTRL_PIN(MX21_PAD_NFIO3), + IMX_PINCTRL_PIN(MX21_PAD_NFIO4), + IMX_PINCTRL_PIN(MX21_PAD_NFIO5), + IMX_PINCTRL_PIN(MX21_PAD_NFIO6), + IMX_PINCTRL_PIN(MX21_PAD_NFIO7), + IMX_PINCTRL_PIN(MX21_PAD_CLKO), + IMX_PINCTRL_PIN(MX21_PAD_RESERVED), + IMX_PINCTRL_PIN(MX21_PAD_CS4), + IMX_PINCTRL_PIN(MX21_PAD_CS5), +}; + +static struct imx1_pinctrl_soc_info imx21_pinctrl_info = { + .pins = imx21_pinctrl_pads, + .npins = ARRAY_SIZE(imx21_pinctrl_pads), +}; + +static int __init imx21_pinctrl_probe(struct platform_device *pdev) +{ + return imx1_pinctrl_core_probe(pdev, &imx21_pinctrl_info); +} + +static const struct of_device_id imx21_pinctrl_of_match[] = { + { .compatible = "fsl,imx21-iomuxc", }, + { } +}; +MODULE_DEVICE_TABLE(of, imx21_pinctrl_of_match); + +static struct platform_driver imx21_pinctrl_driver = { + .driver = { + .name = "imx21-pinctrl", + .owner = THIS_MODULE, + .of_match_table = imx21_pinctrl_of_match, + }, + .remove = imx1_pinctrl_core_remove, +}; +module_platform_driver_probe(imx21_pinctrl_driver, imx21_pinctrl_probe); + +MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); +MODULE_DESCRIPTION("Freescale i.MX21 pinctrl driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/pinctrl-imx23.c b/drivers/pinctrl/freescale/pinctrl-imx23.c index e76d75c9d1ba..df79096becb0 100644 --- a/drivers/pinctrl/pinctrl-imx23.c +++ b/drivers/pinctrl/freescale/pinctrl-imx23.c @@ -272,7 +272,7 @@ static int imx23_pinctrl_probe(struct platform_device *pdev) return mxs_pinctrl_probe(pdev, &imx23_pinctrl_data); } -static struct of_device_id imx23_pinctrl_of_match[] = { +static const struct of_device_id imx23_pinctrl_of_match[] = { { .compatible = "fsl,imx23-pinctrl", }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-imx25.c b/drivers/pinctrl/freescale/pinctrl-imx25.c index 1aae1b61c4dc..550e6d77ac2b 100644 --- a/drivers/pinctrl/pinctrl-imx25.c +++ b/drivers/pinctrl/freescale/pinctrl-imx25.c @@ -315,7 +315,7 @@ static struct imx_pinctrl_soc_info imx25_pinctrl_info = { .npins = ARRAY_SIZE(imx25_pinctrl_pads), }; -static struct of_device_id imx25_pinctrl_of_match[] = { +static const struct of_device_id imx25_pinctrl_of_match[] = { { .compatible = "fsl,imx25-iomuxc", }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-imx27.c b/drivers/pinctrl/freescale/pinctrl-imx27.c index f8dfefb69968..945eccadea74 100644 --- a/drivers/pinctrl/pinctrl-imx27.c +++ b/drivers/pinctrl/freescale/pinctrl-imx27.c @@ -389,7 +389,7 @@ static struct imx1_pinctrl_soc_info imx27_pinctrl_info = { .npins = ARRAY_SIZE(imx27_pinctrl_pads), }; -static struct of_device_id imx27_pinctrl_of_match[] = { +static const struct of_device_id imx27_pinctrl_of_match[] = { { .compatible = "fsl,imx27-iomuxc", }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-imx28.c b/drivers/pinctrl/freescale/pinctrl-imx28.c index 79c9c8d296af..3bd45da21229 100644 --- a/drivers/pinctrl/pinctrl-imx28.c +++ b/drivers/pinctrl/freescale/pinctrl-imx28.c @@ -388,7 +388,7 @@ static int imx28_pinctrl_probe(struct platform_device *pdev) return mxs_pinctrl_probe(pdev, &imx28_pinctrl_data); } -static struct of_device_id imx28_pinctrl_of_match[] = { +static const struct of_device_id imx28_pinctrl_of_match[] = { { .compatible = "fsl,imx28-pinctrl", }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-imx35.c b/drivers/pinctrl/freescale/pinctrl-imx35.c index 278a04ae8940..6bfbcd0112c1 100644 --- a/drivers/pinctrl/pinctrl-imx35.c +++ b/drivers/pinctrl/freescale/pinctrl-imx35.c @@ -1005,7 +1005,7 @@ static struct imx_pinctrl_soc_info imx35_pinctrl_info = { .npins = ARRAY_SIZE(imx35_pinctrl_pads), }; -static struct of_device_id imx35_pinctrl_of_match[] = { +static const struct of_device_id imx35_pinctrl_of_match[] = { { .compatible = "fsl,imx35-iomuxc", }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-imx50.c b/drivers/pinctrl/freescale/pinctrl-imx50.c index b06feed1b038..e8bd604ab147 100644 --- a/drivers/pinctrl/pinctrl-imx50.c +++ b/drivers/pinctrl/freescale/pinctrl-imx50.c @@ -391,7 +391,7 @@ static struct imx_pinctrl_soc_info imx50_pinctrl_info = { .npins = ARRAY_SIZE(imx50_pinctrl_pads), }; -static struct of_device_id imx50_pinctrl_of_match[] = { +static const struct of_device_id imx50_pinctrl_of_match[] = { { .compatible = "fsl,imx50-iomuxc", }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-imx51.c b/drivers/pinctrl/freescale/pinctrl-imx51.c index 19ab182bef61..b818051db7c9 100644 --- a/drivers/pinctrl/pinctrl-imx51.c +++ b/drivers/pinctrl/freescale/pinctrl-imx51.c @@ -768,7 +768,7 @@ static struct imx_pinctrl_soc_info imx51_pinctrl_info = { .npins = ARRAY_SIZE(imx51_pinctrl_pads), }; -static struct of_device_id imx51_pinctrl_of_match[] = { +static const struct of_device_id imx51_pinctrl_of_match[] = { { .compatible = "fsl,imx51-iomuxc", }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-imx53.c b/drivers/pinctrl/freescale/pinctrl-imx53.c index f8d45c4cfde7..1884d53cf750 100644 --- a/drivers/pinctrl/pinctrl-imx53.c +++ b/drivers/pinctrl/freescale/pinctrl-imx53.c @@ -454,7 +454,7 @@ static struct imx_pinctrl_soc_info imx53_pinctrl_info = { .npins = ARRAY_SIZE(imx53_pinctrl_pads), }; -static struct of_device_id imx53_pinctrl_of_match[] = { +static const struct of_device_id imx53_pinctrl_of_match[] = { { .compatible = "fsl,imx53-iomuxc", }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-imx6dl.c b/drivers/pinctrl/freescale/pinctrl-imx6dl.c index db2a1489bd99..656c4b08cc2e 100644 --- a/drivers/pinctrl/pinctrl-imx6dl.c +++ b/drivers/pinctrl/freescale/pinctrl-imx6dl.c @@ -460,7 +460,7 @@ static struct imx_pinctrl_soc_info imx6dl_pinctrl_info = { .npins = ARRAY_SIZE(imx6dl_pinctrl_pads), }; -static struct of_device_id imx6dl_pinctrl_of_match[] = { +static const struct of_device_id imx6dl_pinctrl_of_match[] = { { .compatible = "fsl,imx6dl-iomuxc", }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-imx6q.c b/drivers/pinctrl/freescale/pinctrl-imx6q.c index 8eb5ac1bd5f6..59bb5b4ec0f6 100644 --- a/drivers/pinctrl/pinctrl-imx6q.c +++ b/drivers/pinctrl/freescale/pinctrl-imx6q.c @@ -466,7 +466,7 @@ static struct imx_pinctrl_soc_info imx6q_pinctrl_info = { .npins = ARRAY_SIZE(imx6q_pinctrl_pads), }; -static struct of_device_id imx6q_pinctrl_of_match[] = { +static const struct of_device_id imx6q_pinctrl_of_match[] = { { .compatible = "fsl,imx6q-iomuxc", }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-imx6sl.c b/drivers/pinctrl/freescale/pinctrl-imx6sl.c index f21b7389df3c..e0924bd7b98c 100644 --- a/drivers/pinctrl/pinctrl-imx6sl.c +++ b/drivers/pinctrl/freescale/pinctrl-imx6sl.c @@ -366,10 +366,11 @@ static struct imx_pinctrl_soc_info imx6sl_pinctrl_info = { .npins = ARRAY_SIZE(imx6sl_pinctrl_pads), }; -static struct of_device_id imx6sl_pinctrl_of_match[] = { +static const struct of_device_id imx6sl_pinctrl_of_match[] = { { .compatible = "fsl,imx6sl-iomuxc", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, imx6sl_pinctrl_of_match); static int imx6sl_pinctrl_probe(struct platform_device *pdev) { diff --git a/drivers/pinctrl/pinctrl-imx6sx.c b/drivers/pinctrl/freescale/pinctrl-imx6sx.c index 09758a56b9df..840344c8580d 100644 --- a/drivers/pinctrl/pinctrl-imx6sx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx6sx.c @@ -370,7 +370,7 @@ static struct imx_pinctrl_soc_info imx6sx_pinctrl_info = { .npins = ARRAY_SIZE(imx6sx_pinctrl_pads), }; -static struct of_device_id imx6sx_pinctrl_of_match[] = { +static const struct of_device_id imx6sx_pinctrl_of_match[] = { { .compatible = "fsl,imx6sx-iomuxc", }, { /* sentinel */ } }; diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/freescale/pinctrl-mxs.c index 40c76f26998c..f98c6bb0f769 100644 --- a/drivers/pinctrl/pinctrl-mxs.c +++ b/drivers/pinctrl/freescale/pinctrl-mxs.c @@ -21,7 +21,7 @@ #include <linux/pinctrl/pinmux.h> #include <linux/platform_device.h> #include <linux/slab.h> -#include "core.h" +#include "../core.h" #include "pinctrl-mxs.h" #define SUFFIX_LEN 4 @@ -195,8 +195,8 @@ static int mxs_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, return 0; } -static int mxs_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group) +static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) { struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev); struct mxs_group *g = &d->soc->groups[group]; @@ -223,7 +223,7 @@ static const struct pinmux_ops mxs_pinmux_ops = { .get_functions_count = mxs_pinctrl_get_funcs_count, .get_function_name = mxs_pinctrl_get_func_name, .get_function_groups = mxs_pinctrl_get_func_groups, - .enable = mxs_pinctrl_enable, + .set_mux = mxs_pinctrl_set_mux, }; static int mxs_pinconf_get(struct pinctrl_dev *pctldev, diff --git a/drivers/pinctrl/pinctrl-mxs.h b/drivers/pinctrl/freescale/pinctrl-mxs.h index fdd88d0bae22..fdd88d0bae22 100644 --- a/drivers/pinctrl/pinctrl-mxs.h +++ b/drivers/pinctrl/freescale/pinctrl-mxs.h diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/freescale/pinctrl-vf610.c index bddd913d28ba..b788e1578954 100644 --- a/drivers/pinctrl/pinctrl-vf610.c +++ b/drivers/pinctrl/freescale/pinctrl-vf610.c @@ -299,7 +299,7 @@ static const struct pinctrl_pin_desc vf610_pinctrl_pads[] = { 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, + .flags = SHARE_MUX_CONF_REG, }; static struct of_device_id vf610_pinctrl_of_match[] = { diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index 9908374f8f92..f3b426cdaf8f 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -259,8 +259,8 @@ static int mvebu_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned fid, return 0; } -static int mvebu_pinmux_enable(struct pinctrl_dev *pctldev, unsigned fid, - unsigned gid) +static int mvebu_pinmux_set(struct pinctrl_dev *pctldev, unsigned fid, + unsigned gid) { struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); struct mvebu_pinctrl_function *func = &pctl->functions[fid]; @@ -344,7 +344,7 @@ static const struct pinmux_ops mvebu_pinmux_ops = { .get_function_groups = mvebu_pinmux_get_groups, .gpio_request_enable = mvebu_pinmux_gpio_request_enable, .gpio_set_direction = mvebu_pinmux_gpio_set_direction, - .enable = mvebu_pinmux_enable, + .set_mux = mvebu_pinmux_set, }; static int mvebu_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c index 8c6fd8d4dd3c..47f493149863 100644 --- a/drivers/pinctrl/nomadik/pinctrl-abx500.c +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c @@ -34,6 +34,7 @@ #include "pinctrl-abx500.h" #include "../core.h" #include "../pinconf.h" +#include "../pinctrl-utils.h" /* * The AB9540 and AB8540 GPIO support are extended versions @@ -708,8 +709,8 @@ static int abx500_pmx_get_func_groups(struct pinctrl_dev *pctldev, return 0; } -static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function, - unsigned group) +static int abx500_pmx_set(struct pinctrl_dev *pctldev, unsigned function, + unsigned group) { struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); struct gpio_chip *chip = &pct->chip; @@ -783,7 +784,7 @@ static const struct pinmux_ops abx500_pinmux_ops = { .get_functions_count = abx500_pmx_get_funcs_cnt, .get_function_name = abx500_pmx_get_func_name, .get_function_groups = abx500_pmx_get_func_groups, - .enable = abx500_pmx_enable, + .set_mux = abx500_pmx_set, .gpio_request_enable = abx500_gpio_request_enable, .gpio_disable_free = abx500_gpio_disable_free, }; @@ -826,41 +827,6 @@ 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, @@ -926,19 +892,32 @@ static int abx500_dt_subnode_to_map(struct pinctrl_dev *pctldev, 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; + if (ret >= 0) { + ret = of_property_count_strings(np, "ste,pins"); + if (ret < 0) + goto exit; + + ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, + num_maps, ret); + if (ret < 0) + goto exit; + + of_property_for_each_string(np, "ste,pins", prop, group) { + ret = abx500_dt_add_map_mux(map, reserved_maps, + num_maps, group, function); + if (ret < 0) + goto exit; + } + } 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, @@ -947,28 +926,18 @@ static int abx500_dt_subnode_to_map(struct pinctrl_dev *pctldev, goto exit; has_config |= nconfigs; } + if (has_config) { + ret = of_property_count_strings(np, "ste,pins"); + if (ret < 0) + goto exit; - 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; + ret = pinctrl_utils_reserve_map(pctldev, map, + reserved_maps, + num_maps, ret); + 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) { + of_property_for_each_string(np, "ste,pins", prop, group) { gpio_name = abx500_find_pin_name(pctldev, group); ret = abx500_dt_add_map_configs(map, reserved_maps, @@ -976,8 +945,8 @@ static int abx500_dt_subnode_to_map(struct pinctrl_dev *pctldev, if (ret < 0) goto exit; } - } + exit: return ret; } @@ -998,7 +967,7 @@ static int abx500_dt_node_to_map(struct pinctrl_dev *pctldev, ret = abx500_dt_subnode_to_map(pctldev, np, map, &reserved_maps, num_maps); if (ret < 0) { - abx500_dt_free_map(pctldev, *map, *num_maps); + pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); return ret; } } @@ -1012,7 +981,7 @@ static const struct pinctrl_ops abx500_pinctrl_ops = { .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, + .dt_free_map = pinctrl_utils_dt_free_map, }; static int abx500_pin_config_get(struct pinctrl_dev *pctldev, diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c index e7cab07eef47..3c29d9187146 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -32,6 +32,7 @@ #include <linux/pinctrl/consumer.h> #include "pinctrl-nomadik.h" #include "../core.h" +#include "../pinctrl-utils.h" /* * The GPIO module in the Nomadik family of Systems-on-Chip is an @@ -985,6 +986,7 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s, container_of(chip, struct nmk_gpio_chip, chip); int mode; bool is_out; + bool data_out; bool pull; u32 bit = 1 << offset; const char *modes[] = { @@ -997,28 +999,41 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s, [NMK_GPIO_ALT_C+3] = "altC3", [NMK_GPIO_ALT_C+4] = "altC4", }; + const char *pulls[] = { + "none ", + "pull down", + "pull up ", + }; clk_enable(nmk_chip->clk); is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & bit); pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit); + data_out = !!(readl(nmk_chip->addr + NMK_GPIO_DAT) & bit); mode = nmk_gpio_get_mode(gpio); if ((mode == NMK_GPIO_ALT_C) && pctldev) mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio); - seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s", - gpio, label ?: "(none)", - is_out ? "out" : "in ", - chip->get - ? (chip->get(chip, offset) ? "hi" : "lo") - : "? ", - (mode < 0) ? "unknown" : modes[mode], - pull ? "pull" : "none"); - - if (!is_out) { + if (is_out) { + seq_printf(s, " gpio-%-3d (%-20.20s) out %s %s", + gpio, + label ?: "(none)", + data_out ? "hi" : "lo", + (mode < 0) ? "unknown" : modes[mode]); + } else { int irq = gpio_to_irq(gpio); struct irq_desc *desc = irq_to_desc(irq); + int pullidx = 0; - /* This races with request_irq(), set_irq_type(), + if (pull) + pullidx = data_out ? 1 : 2; + + seq_printf(s, " gpio-%-3d (%-20.20s) in %s %s", + gpio, + label ?: "(none)", + pulls[pullidx], + (mode < 0) ? "unknown" : modes[mode]); + /* + * This races with request_irq(), set_irq_type(), * and set_irq_wake() ... but those are "rare". */ if (irq > 0 && desc && desc->action) { @@ -1338,39 +1353,6 @@ static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset); } -static void nmk_pinctrl_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 nmk_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 nmk_dt_add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps, unsigned *num_maps, const char *group, const char *function) @@ -1537,51 +1519,55 @@ static int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, const char *function = NULL; unsigned long configs = 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; - - has_config = nmk_pinctrl_dt_get_config(np, &configs); - - np_config = of_parse_phandle(np, "ste,config", 0); - if (np_config) - has_config |= nmk_pinctrl_dt_get_config(np_config, &configs); - - ret = of_property_count_strings(np, "ste,pins"); - if (ret < 0) - goto exit; - - if (has_config) - reserve++; - - reserve *= ret; - - ret = nmk_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) { + if (ret >= 0) { + ret = of_property_count_strings(np, "ste,pins"); + if (ret < 0) + goto exit; + + ret = pinctrl_utils_reserve_map(pctldev, map, + reserved_maps, + num_maps, ret); + if (ret < 0) + goto exit; + + of_property_for_each_string(np, "ste,pins", prop, group) { ret = nmk_dt_add_map_mux(map, reserved_maps, num_maps, group, function); if (ret < 0) goto exit; } - if (has_config) { + } + + has_config = nmk_pinctrl_dt_get_config(np, &configs); + np_config = of_parse_phandle(np, "ste,config", 0); + if (np_config) + has_config |= nmk_pinctrl_dt_get_config(np_config, &configs); + if (has_config) { + ret = of_property_count_strings(np, "ste,pins"); + if (ret < 0) + goto exit; + ret = pinctrl_utils_reserve_map(pctldev, map, + reserved_maps, + num_maps, ret); + if (ret < 0) + goto exit; + + of_property_for_each_string(np, "ste,pins", prop, group) { gpio_name = nmk_find_pin_name(pctldev, group); - ret = nmk_dt_add_map_configs(map, reserved_maps, num_maps, - gpio_name, &configs, 1); + ret = nmk_dt_add_map_configs(map, reserved_maps, + num_maps, + gpio_name, &configs, 1); if (ret < 0) goto exit; } - } + exit: return ret; } @@ -1602,7 +1588,7 @@ static int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, ret = nmk_pinctrl_dt_subnode_to_map(pctldev, np, map, &reserved_maps, num_maps); if (ret < 0) { - nmk_pinctrl_dt_free_map(pctldev, *map, *num_maps); + pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); return ret; } } @@ -1616,7 +1602,7 @@ static const struct pinctrl_ops nmk_pinctrl_ops = { .get_group_pins = nmk_get_group_pins, .pin_dbg_show = nmk_pin_dbg_show, .dt_node_to_map = nmk_pinctrl_dt_node_to_map, - .dt_free_map = nmk_pinctrl_dt_free_map, + .dt_free_map = pinctrl_utils_dt_free_map, }; static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) @@ -1647,8 +1633,8 @@ static int nmk_pmx_get_func_groups(struct pinctrl_dev *pctldev, return 0; } -static int nmk_pmx_enable(struct pinctrl_dev *pctldev, unsigned function, - unsigned group) +static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned function, + unsigned group) { struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); const struct nmk_pingroup *g; @@ -1810,7 +1796,7 @@ static const struct pinmux_ops nmk_pinmux_ops = { .get_functions_count = nmk_pmx_get_funcs_cnt, .get_function_name = nmk_pmx_get_func_name, .get_function_groups = nmk_pmx_get_func_groups, - .enable = nmk_pmx_enable, + .set_mux = nmk_pmx_set, .gpio_request_enable = nmk_gpio_request_enable, .gpio_disable_free = nmk_gpio_disable_free, }; diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c index b092b93c67a1..8434439c5017 100644 --- a/drivers/pinctrl/pinctrl-adi2.c +++ b/drivers/pinctrl/pinctrl-adi2.c @@ -619,8 +619,8 @@ static struct pinctrl_ops adi_pctrl_ops = { .get_group_pins = adi_get_group_pins, }; -static int adi_pinmux_enable(struct pinctrl_dev *pctldev, unsigned func_id, - unsigned group_id) +static int adi_pinmux_set(struct pinctrl_dev *pctldev, unsigned func_id, + unsigned group_id) { struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); struct gpio_port *port; @@ -698,7 +698,7 @@ static int adi_pinmux_request_gpio(struct pinctrl_dev *pctldev, } static struct pinmux_ops adi_pinmux_ops = { - .enable = adi_pinmux_enable, + .set_mux = adi_pinmux_set, .get_functions_count = adi_pinmux_get_funcs_count, .get_function_name = adi_pinmux_get_func_name, .get_function_groups = adi_pinmux_get_groups, @@ -1041,7 +1041,6 @@ static int adi_gpio_remove(struct platform_device *pdev) u8 offset; list_del(&port->node); - gpiochip_remove_pin_ranges(&port->chip); gpiochip_remove(&port->chip); if (port->pint) { for (offset = 0; offset < port->width; offset++) diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c index 0e4ec91f4d49..1f790a4b83fe 100644 --- a/drivers/pinctrl/pinctrl-as3722.c +++ b/drivers/pinctrl/pinctrl-as3722.c @@ -230,7 +230,7 @@ static int as3722_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, return 0; } -static int as3722_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function, +static int as3722_pinctrl_set(struct pinctrl_dev *pctldev, unsigned function, unsigned group) { struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); @@ -327,7 +327,7 @@ static const struct pinmux_ops as3722_pinmux_ops = { .get_functions_count = as3722_pinctrl_get_funcs_count, .get_function_name = as3722_pinctrl_get_func_name, .get_function_groups = as3722_pinctrl_get_func_groups, - .enable = as3722_pinctrl_enable, + .set_mux = as3722_pinctrl_set, .gpio_request_enable = as3722_pinctrl_gpio_request_enable, .gpio_set_direction = as3722_pinctrl_gpio_set_direction, }; diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 60464a2648aa..354a81d40925 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -58,11 +58,28 @@ static int gpio_banks; #define DEGLITCH (1 << 2) #define PULL_DOWN (1 << 3) #define DIS_SCHMIT (1 << 4) +#define DRIVE_STRENGTH_SHIFT 5 +#define DRIVE_STRENGTH_MASK 0x3 +#define DRIVE_STRENGTH (DRIVE_STRENGTH_MASK << DRIVE_STRENGTH_SHIFT) #define DEBOUNCE (1 << 16) #define DEBOUNCE_VAL_SHIFT 17 #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT) /** + * These defines will translated the dt binding settings to our internal + * settings. They are not necessarily the same value as the register setting. + * The actual drive strength current of low, medium and high must be looked up + * from the corresponding device datasheet. This value is different for pins + * that are even in the same banks. It is also dependent on VCC. + * DRIVE_STRENGTH_DEFAULT is just a placeholder to avoid changing the drive + * strength when there is no dt config for it. + */ +#define DRIVE_STRENGTH_DEFAULT (0 << DRIVE_STRENGTH_SHIFT) +#define DRIVE_STRENGTH_LOW (1 << DRIVE_STRENGTH_SHIFT) +#define DRIVE_STRENGTH_MED (2 << DRIVE_STRENGTH_SHIFT) +#define DRIVE_STRENGTH_HI (3 << DRIVE_STRENGTH_SHIFT) + +/** * struct at91_pmx_func - describes AT91 pinmux functions * @name: the name of this specific function * @groups: corresponding pin groups @@ -148,6 +165,9 @@ struct at91_pinctrl_mux_ops { void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on); bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin); void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask); + unsigned (*get_drivestrength)(void __iomem *pio, unsigned pin); + void (*set_drivestrength)(void __iomem *pio, unsigned pin, + u32 strength); /* irq */ int (*irq_type)(struct irq_data *d, unsigned type); }; @@ -315,6 +335,30 @@ static unsigned pin_to_mask(unsigned int pin) return 1 << pin; } +static unsigned two_bit_pin_value_shift_amount(unsigned int pin) +{ + /* return the shift value for a pin for "two bit" per pin registers, + * i.e. drive strength */ + return 2*((pin >= MAX_NB_GPIO_PER_BANK/2) + ? pin - MAX_NB_GPIO_PER_BANK/2 : pin); +} + +static unsigned sama5d3_get_drive_register(unsigned int pin) +{ + /* drive strength is split between two registers + * with two bits per pin */ + return (pin >= MAX_NB_GPIO_PER_BANK/2) + ? SAMA5D3_PIO_DRIVER2 : SAMA5D3_PIO_DRIVER1; +} + +static unsigned at91sam9x5_get_drive_register(unsigned int pin) +{ + /* drive strength is split between two registers + * with two bits per pin */ + return (pin >= MAX_NB_GPIO_PER_BANK/2) + ? AT91SAM9X5_PIO_DRIVER2 : AT91SAM9X5_PIO_DRIVER1; +} + static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask) { writel_relaxed(mask, pio + PIO_IDR); @@ -327,6 +371,9 @@ static unsigned at91_mux_get_pullup(void __iomem *pio, unsigned pin) static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on) { + if (on) + writel_relaxed(mask, pio + PIO_PPDDR); + writel_relaxed(mask, pio + (on ? PIO_PUER : PIO_PUDR)); } @@ -455,6 +502,9 @@ static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin) static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on) { + if (is_on) + __raw_writel(mask, pio + PIO_PUDR); + __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR)); } @@ -468,6 +518,79 @@ static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin) return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1; } +static inline u32 read_drive_strength(void __iomem *reg, unsigned pin) +{ + unsigned tmp = __raw_readl(reg); + + tmp = tmp >> two_bit_pin_value_shift_amount(pin); + + return tmp & DRIVE_STRENGTH_MASK; +} + +static unsigned at91_mux_sama5d3_get_drivestrength(void __iomem *pio, + unsigned pin) +{ + unsigned tmp = read_drive_strength(pio + + sama5d3_get_drive_register(pin), pin); + + /* SAMA5 strength is 1:1 with our defines, + * except 0 is equivalent to low per datasheet */ + if (!tmp) + tmp = DRIVE_STRENGTH_LOW; + + return tmp; +} + +static unsigned at91_mux_sam9x5_get_drivestrength(void __iomem *pio, + unsigned pin) +{ + unsigned tmp = read_drive_strength(pio + + at91sam9x5_get_drive_register(pin), pin); + + /* strength is inverse in SAM9x5s hardware with the pinctrl defines + * hardware: 0 = hi, 1 = med, 2 = low, 3 = rsvd */ + tmp = DRIVE_STRENGTH_HI - tmp; + + return tmp; +} + +static void set_drive_strength(void __iomem *reg, unsigned pin, u32 strength) +{ + unsigned tmp = __raw_readl(reg); + unsigned shift = two_bit_pin_value_shift_amount(pin); + + tmp &= ~(DRIVE_STRENGTH_MASK << shift); + tmp |= strength << shift; + + __raw_writel(tmp, reg); +} + +static void at91_mux_sama5d3_set_drivestrength(void __iomem *pio, unsigned pin, + u32 setting) +{ + /* do nothing if setting is zero */ + if (!setting) + return; + + /* strength is 1 to 1 with setting for SAMA5 */ + set_drive_strength(pio + sama5d3_get_drive_register(pin), pin, setting); +} + +static void at91_mux_sam9x5_set_drivestrength(void __iomem *pio, unsigned pin, + u32 setting) +{ + /* do nothing if setting is zero */ + if (!setting) + return; + + /* strength is inverse on SAM9x5s with our defines + * 0 = hi, 1 = med, 2 = low, 3 = rsvd */ + setting = DRIVE_STRENGTH_HI - setting; + + set_drive_strength(pio + at91sam9x5_get_drive_register(pin), pin, + setting); +} + static struct at91_pinctrl_mux_ops at91rm9200_ops = { .get_periph = at91_mux_get_periph, .mux_A_periph = at91_mux_set_A_periph, @@ -491,6 +614,27 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = { .set_pulldown = at91_mux_pio3_set_pulldown, .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig, .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig, + .get_drivestrength = at91_mux_sam9x5_get_drivestrength, + .set_drivestrength = at91_mux_sam9x5_set_drivestrength, + .irq_type = alt_gpio_irq_type, +}; + +static struct at91_pinctrl_mux_ops sama5d3_ops = { + .get_periph = at91_mux_pio3_get_periph, + .mux_A_periph = at91_mux_pio3_set_A_periph, + .mux_B_periph = at91_mux_pio3_set_B_periph, + .mux_C_periph = at91_mux_pio3_set_C_periph, + .mux_D_periph = at91_mux_pio3_set_D_periph, + .get_deglitch = at91_mux_pio3_get_deglitch, + .set_deglitch = at91_mux_pio3_set_deglitch, + .get_debounce = at91_mux_pio3_get_debounce, + .set_debounce = at91_mux_pio3_set_debounce, + .get_pulldown = at91_mux_pio3_get_pulldown, + .set_pulldown = at91_mux_pio3_set_pulldown, + .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig, + .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig, + .get_drivestrength = at91_mux_sama5d3_get_drivestrength, + .set_drivestrength = at91_mux_sama5d3_set_drivestrength, .irq_type = alt_gpio_irq_type, }; @@ -554,8 +698,8 @@ static void at91_mux_gpio_enable(void __iomem *pio, unsigned mask, bool input) writel_relaxed(mask, pio + (input ? PIO_ODR : PIO_OER)); } -static int at91_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group) +static int at91_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) { struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf; @@ -684,7 +828,7 @@ static const struct pinmux_ops at91_pmx_ops = { .get_functions_count = at91_pmx_get_funcs_count, .get_function_name = at91_pmx_get_func_name, .get_function_groups = at91_pmx_get_groups, - .enable = at91_pmx_enable, + .set_mux = at91_pmx_set, .gpio_request_enable = at91_gpio_request_enable, .gpio_disable_free = at91_gpio_disable_free, }; @@ -716,6 +860,9 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev, *config |= PULL_DOWN; if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin)) *config |= DIS_SCHMIT; + if (info->ops->get_drivestrength) + *config |= (info->ops->get_drivestrength(pio, pin) + << DRIVE_STRENGTH_SHIFT); return 0; } @@ -729,6 +876,7 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, void __iomem *pio; int i; unsigned long config; + unsigned pin; for (i = 0; i < num_configs; i++) { config = configs[i]; @@ -737,7 +885,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, config); pio = pin_to_controller(info, pin_to_bank(pin_id)); - mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK); + pin = pin_id % MAX_NB_GPIO_PER_BANK; + mask = pin_to_mask(pin); if (config & PULL_UP && config & PULL_DOWN) return -EINVAL; @@ -753,6 +902,10 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, info->ops->set_pulldown(pio, mask, config & PULL_DOWN); if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT) info->ops->disable_schmitt_trig(pio, mask); + if (info->ops->set_drivestrength) + info->ops->set_drivestrength(pio, pin, + (config & DRIVE_STRENGTH) + >> DRIVE_STRENGTH_SHIFT); } /* for each config */ @@ -768,6 +921,15 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, } \ } while (0) +#define DBG_SHOW_FLAG_MASKED(mask,flag) do { \ + if ((config & mask) == flag) { \ + if (num_conf) \ + seq_puts(s, "|"); \ + seq_puts(s, #flag); \ + num_conf++; \ + } \ +} while (0) + static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned pin_id) { @@ -781,6 +943,9 @@ static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev, DBG_SHOW_FLAG(PULL_DOWN); DBG_SHOW_FLAG(DIS_SCHMIT); DBG_SHOW_FLAG(DEGLITCH); + DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_LOW); + DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_MED); + DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_HI); DBG_SHOW_FLAG(DEBOUNCE); if (config & DEBOUNCE) { val = config >> DEBOUNCE_VAL_SHIFT; @@ -945,6 +1110,7 @@ static int at91_pinctrl_parse_functions(struct device_node *np, } static struct of_device_id at91_pinctrl_of_match[] = { + { .compatible = "atmel,sama5d3-pinctrl", .data = &sama5d3_ops }, { .compatible = "atmel,at91sam9x5-pinctrl", .data = &at91sam9x5_ops }, { .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops }, { /* sentinel */ } @@ -1445,7 +1611,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) /* now it may re-trigger */ } -static int at91_gpio_of_irq_setup(struct device_node *node, +static int at91_gpio_of_irq_setup(struct platform_device *pdev, struct at91_gpio_chip *at91_gpio) { struct at91_gpio_chip *prev = NULL; @@ -1470,9 +1636,11 @@ static int at91_gpio_of_irq_setup(struct device_node *node, 0, handle_edge_irq, IRQ_TYPE_EDGE_BOTH); - if (ret) - panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n", + if (ret) { + dev_err(&pdev->dev, "at91_gpio.%d: Couldn't add irqchip to gpiochip.\n", at91_gpio->pioc_idx); + return ret; + } /* Setup chained handler */ if (at91_gpio->pioc_idx) @@ -1575,19 +1743,22 @@ static int at91_gpio_probe(struct platform_device *pdev) at91_chip->pioc_virq = irq; at91_chip->pioc_idx = alias_idx; - at91_chip->clock = clk_get(&pdev->dev, NULL); + at91_chip->clock = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(at91_chip->clock)) { dev_err(&pdev->dev, "failed to get clock, ignoring.\n"); + ret = PTR_ERR(at91_chip->clock); goto err; } - if (clk_prepare(at91_chip->clock)) - goto clk_prep_err; + ret = clk_prepare(at91_chip->clock); + if (ret) + goto clk_prepare_err; /* enable PIO controller's clock */ - if (clk_enable(at91_chip->clock)) { + ret = clk_enable(at91_chip->clock); + if (ret) { dev_err(&pdev->dev, "failed to enable clock, ignoring.\n"); - goto clk_err; + goto clk_enable_err; } at91_chip->chip = at91_gpio_template; @@ -1612,7 +1783,7 @@ static int at91_gpio_probe(struct platform_device *pdev) if (!names) { ret = -ENOMEM; - goto clk_err; + goto clk_enable_err; } for (i = 0; i < chip->ngpio; i++) @@ -1630,23 +1801,28 @@ static int at91_gpio_probe(struct platform_device *pdev) ret = gpiochip_add(chip); if (ret) - goto clk_err; + goto gpiochip_add_err; gpio_chips[alias_idx] = at91_chip; gpio_banks = max(gpio_banks, alias_idx + 1); at91_gpio_probe_fixup(); - at91_gpio_of_irq_setup(np, at91_chip); + ret = at91_gpio_of_irq_setup(pdev, at91_chip); + if (ret) + goto irq_setup_err; dev_info(&pdev->dev, "at address %p\n", at91_chip->regbase); return 0; -clk_err: +irq_setup_err: + gpiochip_remove(chip); +gpiochip_add_err: + clk_disable(at91_chip->clock); +clk_enable_err: clk_unprepare(at91_chip->clock); -clk_prep_err: - clk_put(at91_chip->clock); +clk_prepare_err: err: dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx); diff --git a/drivers/pinctrl/pinctrl-bcm281xx.c b/drivers/pinctrl/pinctrl-bcm281xx.c index c5ca9e633fff..a26e0c2ba33e 100644 --- a/drivers/pinctrl/pinctrl-bcm281xx.c +++ b/drivers/pinctrl/pinctrl-bcm281xx.c @@ -1055,9 +1055,9 @@ static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev, return 0; } -static int bcm281xx_pinmux_enable(struct pinctrl_dev *pctldev, - unsigned function, - unsigned group) +static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) { struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); const struct bcm281xx_pin_function *f = &pdata->functions[function]; @@ -1084,7 +1084,7 @@ static struct pinmux_ops bcm281xx_pinctrl_pinmux_ops = { .get_functions_count = bcm281xx_pinctrl_get_fcns_count, .get_function_name = bcm281xx_pinctrl_get_fcn_name, .get_function_groups = bcm281xx_pinctrl_get_fcn_groups, - .enable = bcm281xx_pinmux_enable, + .set_mux = bcm281xx_pinmux_set, }; static int bcm281xx_pinctrl_pin_config_get(struct pinctrl_dev *pctldev, diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c index 5bcfd7ace0cd..eabba02f71f9 100644 --- a/drivers/pinctrl/pinctrl-bcm2835.c +++ b/drivers/pinctrl/pinctrl-bcm2835.c @@ -830,7 +830,7 @@ static int bcm2835_pmx_get_function_groups(struct pinctrl_dev *pctldev, return 0; } -static int bcm2835_pmx_enable(struct pinctrl_dev *pctldev, +static int bcm2835_pmx_set(struct pinctrl_dev *pctldev, unsigned func_selector, unsigned group_selector) { @@ -869,7 +869,7 @@ static const struct pinmux_ops bcm2835_pmx_ops = { .get_functions_count = bcm2835_pmx_get_functions_count, .get_function_name = bcm2835_pmx_get_function_name, .get_function_groups = bcm2835_pmx_get_function_groups, - .enable = bcm2835_pmx_enable, + .set_mux = bcm2835_pmx_set, .gpio_disable_free = bcm2835_pmx_gpio_disable_free, .gpio_set_direction = bcm2835_pmx_gpio_set_direction, }; diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c index d22ca252b80d..296e5b37f768 100644 --- a/drivers/pinctrl/pinctrl-lantiq.c +++ b/drivers/pinctrl/pinctrl-lantiq.c @@ -257,9 +257,9 @@ static int match_group_mux(const struct ltq_pin_group *grp, return ret; } -static int ltq_pmx_enable(struct pinctrl_dev *pctrldev, - unsigned func, - unsigned group) +static int ltq_pmx_set(struct pinctrl_dev *pctrldev, + unsigned func, + unsigned group) { struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev); const struct ltq_pin_group *pin_grp = &info->grps[group]; @@ -316,7 +316,7 @@ static const struct pinmux_ops ltq_pmx_ops = { .get_functions_count = ltq_pmx_func_count, .get_function_name = ltq_pmx_func_name, .get_function_groups = ltq_pmx_get_groups, - .enable = ltq_pmx_enable, + .set_mux = ltq_pmx_set, .gpio_request_enable = ltq_pmx_gpio_request_enable, }; diff --git a/drivers/pinctrl/pinctrl-palmas.c b/drivers/pinctrl/pinctrl-palmas.c index f13d0e78a41c..e3079d3d19fe 100644 --- a/drivers/pinctrl/pinctrl-palmas.c +++ b/drivers/pinctrl/pinctrl-palmas.c @@ -685,7 +685,8 @@ static int palmas_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, return 0; } -static int palmas_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function, +static int palmas_pinctrl_set_mux(struct pinctrl_dev *pctldev, + unsigned function, unsigned group) { struct palmas_pctrl_chip_info *pci = pinctrl_dev_get_drvdata(pctldev); @@ -742,7 +743,7 @@ static const struct pinmux_ops palmas_pinmux_ops = { .get_functions_count = palmas_pinctrl_get_funcs_count, .get_function_name = palmas_pinctrl_get_func_name, .get_function_groups = palmas_pinctrl_get_func_groups, - .enable = palmas_pinctrl_enable, + .set_mux = palmas_pinctrl_set_mux, }; static int palmas_pinconf_get(struct pinctrl_dev *pctldev, diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 0c372a300cb8..016f4578e494 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -816,8 +816,8 @@ static int rockchip_pmx_get_groups(struct pinctrl_dev *pctldev, return 0; } -static int rockchip_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group) +static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) { struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); const unsigned int *pins = info->groups[group].pins; @@ -892,7 +892,7 @@ static const struct pinmux_ops rockchip_pmx_ops = { .get_functions_count = rockchip_pmx_get_funcs_count, .get_function_name = rockchip_pmx_get_func_name, .get_function_groups = rockchip_pmx_get_groups, - .enable = rockchip_pmx_enable, + .set_mux = rockchip_pmx_set, .gpio_set_direction = rockchip_pmx_gpio_set_direction, }; diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 95dd9cf55cb3..fb94b772ad62 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -447,7 +447,7 @@ static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin, return 0; } -static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector, +static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector, unsigned group) { struct pcs_device *pcs; @@ -519,7 +519,7 @@ static const struct pinmux_ops pcs_pinmux_ops = { .get_functions_count = pcs_get_functions_count, .get_function_name = pcs_get_function_name, .get_function_groups = pcs_get_function_groups, - .enable = pcs_enable, + .set_mux = pcs_set_mux, .gpio_request_enable = pcs_request_gpio, }; @@ -1981,6 +1981,18 @@ static const struct pcs_soc_data pinctrl_single_omap_wkup = { .irq_status_mask = (1 << 15), /* OMAP_WAKEUP_EVENT */ }; +static const struct pcs_soc_data pinctrl_single_dra7 = { + .flags = PCS_QUIRK_SHARED_IRQ, + .irq_enable_mask = (1 << 24), /* WAKEUPENABLE */ + .irq_status_mask = (1 << 25), /* WAKEUPEVENT */ +}; + +static const struct pcs_soc_data pinctrl_single_am437x = { + .flags = PCS_QUIRK_SHARED_IRQ, + .irq_enable_mask = (1 << 29), /* OMAP_WAKEUP_EN */ + .irq_status_mask = (1 << 30), /* OMAP_WAKEUP_EVENT */ +}; + static const struct pcs_soc_data pinctrl_single = { }; @@ -1992,6 +2004,8 @@ static struct of_device_id pcs_of_match[] = { { .compatible = "ti,omap3-padconf", .data = &pinctrl_single_omap_wkup }, { .compatible = "ti,omap4-padconf", .data = &pinctrl_single_omap_wkup }, { .compatible = "ti,omap5-padconf", .data = &pinctrl_single_omap_wkup }, + { .compatible = "ti,dra7-padconf", .data = &pinctrl_single_dra7 }, + { .compatible = "ti,am437-padconf", .data = &pinctrl_single_am437x }, { .compatible = "pinctrl-single", .data = &pinctrl_single }, { .compatible = "pinconf-single", .data = &pinconf_single }, { }, diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index 5475374d803f..4b1792aad3d8 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -914,8 +914,8 @@ static struct st_pio_control *st_get_pio_control( return &bank->pc; } -static int st_pmx_enable(struct pinctrl_dev *pctldev, unsigned fselector, - unsigned group) +static int st_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned fselector, + unsigned group) { struct st_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); struct st_pinconf *conf = info->groups[group].pin_conf; @@ -951,7 +951,7 @@ static struct pinmux_ops st_pmxops = { .get_functions_count = st_pmx_get_funcs_count, .get_function_name = st_pmx_get_fname, .get_function_groups = st_pmx_get_groups, - .enable = st_pmx_enable, + .set_mux = st_pmx_set_mux, .gpio_set_direction = st_pmx_set_gpio_direction, }; @@ -1517,6 +1517,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info, 0, handle_simple_irq, IRQ_TYPE_LEVEL_LOW); if (err) { + gpiochip_remove(&bank->gpio_chip); dev_info(dev, "could not add irqchip\n"); return err; } diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c index 71c5d4f0c538..3b9bfcf717ac 100644 --- a/drivers/pinctrl/pinctrl-tb10x.c +++ b/drivers/pinctrl/pinctrl-tb10x.c @@ -697,7 +697,7 @@ static void tb10x_gpio_disable_free(struct pinctrl_dev *pctl, mutex_unlock(&state->mutex); } -static int tb10x_pctl_enable(struct pinctrl_dev *pctl, +static int tb10x_pctl_set_mux(struct pinctrl_dev *pctl, unsigned func_selector, unsigned group_selector) { struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl); @@ -744,7 +744,7 @@ static struct pinmux_ops tb10x_pinmux_ops = { .get_function_groups = tb10x_get_function_groups, .gpio_request_enable = tb10x_gpio_request_enable, .gpio_disable_free = tb10x_gpio_disable_free, - .enable = tb10x_pctl_enable, + .set_mux = tb10x_pctl_set_mux, }; static struct pinctrl_desc tb10x_pindesc = { diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c index e641b4226c42..1631ec94fb02 100644 --- a/drivers/pinctrl/pinctrl-tegra-xusb.c +++ b/drivers/pinctrl/pinctrl-tegra-xusb.c @@ -281,9 +281,9 @@ static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl, return 0; } -static int tegra_xusb_padctl_pinmux_enable(struct pinctrl_dev *pinctrl, - unsigned int function, - unsigned int group) +static int tegra_xusb_padctl_pinmux_set(struct pinctrl_dev *pinctrl, + unsigned int function, + unsigned int group) { struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); const struct tegra_xusb_padctl_lane *lane; @@ -311,7 +311,7 @@ static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = { .get_functions_count = tegra_xusb_padctl_get_functions_count, .get_function_name = tegra_xusb_padctl_get_function_name, .get_function_groups = tegra_xusb_padctl_get_function_groups, - .enable = tegra_xusb_padctl_pinmux_enable, + .set_mux = tegra_xusb_padctl_pinmux_set, }; static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl, diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index 150af5503c09..e5949d51bc52 100644 --- a/drivers/pinctrl/pinctrl-tegra.c +++ b/drivers/pinctrl/pinctrl-tegra.c @@ -262,8 +262,9 @@ static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, return 0; } -static int tegra_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function, - unsigned group) +static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) { struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); const struct tegra_pingroup *g; @@ -294,7 +295,7 @@ static const struct pinmux_ops tegra_pinmux_ops = { .get_functions_count = tegra_pinctrl_get_funcs_count, .get_function_name = tegra_pinctrl_get_func_name, .get_function_groups = tegra_pinctrl_get_func_groups, - .enable = tegra_pinctrl_enable, + .set_mux = tegra_pinctrl_set_mux, }; static int tegra_pinconf_reg(struct tegra_pmx *pmx, diff --git a/drivers/pinctrl/pinctrl-tegra114.c b/drivers/pinctrl/pinctrl-tegra114.c index 33614baab4c0..a3db85b0b75f 100644 --- a/drivers/pinctrl/pinctrl-tegra114.c +++ b/drivers/pinctrl/pinctrl-tegra114.c @@ -1850,7 +1850,7 @@ static int tegra114_pinctrl_probe(struct platform_device *pdev) return tegra_pinctrl_probe(pdev, &tegra114_pinctrl); } -static struct of_device_id tegra114_pinctrl_of_match[] = { +static const struct of_device_id tegra114_pinctrl_of_match[] = { { .compatible = "nvidia,tegra114-pinmux", }, { }, }; diff --git a/drivers/pinctrl/pinctrl-tegra124.c b/drivers/pinctrl/pinctrl-tegra124.c index e80797e20017..2f9b75c14967 100644 --- a/drivers/pinctrl/pinctrl-tegra124.c +++ b/drivers/pinctrl/pinctrl-tegra124.c @@ -224,6 +224,16 @@ #define TEGRA_PIN_OWR _PIN(5) #define TEGRA_PIN_CLK_32K_IN _PIN(6) #define TEGRA_PIN_JTAG_RTCK _PIN(7) +#define TEGRA_PIN_DSI_B_CLK_P _PIN(8) +#define TEGRA_PIN_DSI_B_CLK_N _PIN(9) +#define TEGRA_PIN_DSI_B_D0_P _PIN(10) +#define TEGRA_PIN_DSI_B_D0_N _PIN(11) +#define TEGRA_PIN_DSI_B_D1_P _PIN(12) +#define TEGRA_PIN_DSI_B_D1_N _PIN(13) +#define TEGRA_PIN_DSI_B_D2_P _PIN(14) +#define TEGRA_PIN_DSI_B_D2_N _PIN(15) +#define TEGRA_PIN_DSI_B_D3_P _PIN(16) +#define TEGRA_PIN_DSI_B_D3_N _PIN(17) static const struct pinctrl_pin_desc tegra124_pins[] = { PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), @@ -417,6 +427,16 @@ static const struct pinctrl_pin_desc tegra124_pins[] = { PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_P, "DSI_B_CLK_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_N, "DSI_B_CLK_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_P, "DSI_B_D0_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_N, "DSI_B_D0_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_P, "DSI_B_D1_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_N, "DSI_B_D1_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_P, "DSI_B_D2_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_N, "DSI_B_D2_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_P, "DSI_B_D3_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_N, "DSI_B_D3_N"), }; static const unsigned clk_32k_out_pa0_pins[] = { @@ -1495,6 +1515,19 @@ static const unsigned drive_ao4_pins[] = { TEGRA_PIN_JTAG_RTCK, }; +static const unsigned mipi_pad_ctrl_dsi_b_pins[] = { + TEGRA_PIN_DSI_B_CLK_P, + TEGRA_PIN_DSI_B_CLK_N, + TEGRA_PIN_DSI_B_D0_P, + TEGRA_PIN_DSI_B_D0_N, + TEGRA_PIN_DSI_B_D1_P, + TEGRA_PIN_DSI_B_D1_N, + TEGRA_PIN_DSI_B_D2_P, + TEGRA_PIN_DSI_B_D2_N, + TEGRA_PIN_DSI_B_D3_P, + TEGRA_PIN_DSI_B_D3_N, +}; + enum tegra_mux { TEGRA_MUX_BLINK, TEGRA_MUX_CCLA, @@ -1580,6 +1613,8 @@ enum tegra_mux { TEGRA_MUX_VI_ALT3, TEGRA_MUX_VIMCLK2, TEGRA_MUX_VIMCLK2_ALT, + TEGRA_MUX_CSI, + TEGRA_MUX_DSI_B, }; #define FUNCTION(fname) \ @@ -1672,10 +1707,13 @@ static struct tegra_function tegra124_functions[] = { FUNCTION(vi_alt3), FUNCTION(vimclk2), FUNCTION(vimclk2_alt), + FUNCTION(csi), + FUNCTION(dsi_b), }; #define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ #define PINGROUP_REG_A 0x3000 /* bank 1 */ +#define MIPI_PAD_CTRL_PINGROUP_REG_A 0x820 /* bank 2 */ #define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) @@ -1744,6 +1782,32 @@ static struct tegra_function tegra124_functions[] = { .drvtype_bit = PINGROUP_BIT_##drvtype(6), \ } +#define MIPI_PAD_CTRL_PINGROUP_REG_Y(r) ((r) - MIPI_PAD_CTRL_PINGROUP_REG_A) + +#define MIPI_PAD_CTRL_PINGROUP(pg_name, r, b, f0, f1) \ + { \ + .name = "mipi_pad_ctrl_" #pg_name, \ + .pins = mipi_pad_ctrl_##pg_name##_pins, \ + .npins = ARRAY_SIZE(mipi_pad_ctrl_##pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_ ## f0, \ + TEGRA_MUX_ ## f1, \ + TEGRA_MUX_RSVD3, \ + TEGRA_MUX_RSVD4, \ + }, \ + .mux_reg = MIPI_PAD_CTRL_PINGROUP_REG_Y(r), \ + .mux_bank = 2, \ + .mux_bit = b, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = -1, \ + } + static const struct tegra_pingroup tegra124_groups[] = { /* pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel */ PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N, N), @@ -1979,6 +2043,9 @@ static const struct tegra_pingroup tegra124_groups[] = { DRV_PINGROUP(hv0, 0x9b4, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), DRV_PINGROUP(sdio4, 0x9c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), DRV_PINGROUP(ao4, 0x9c8, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + + /* pg_name, r b f0, f1 */ + MIPI_PAD_CTRL_PINGROUP(dsi_b, 0x820, 1, CSI, DSI_B) }; static const struct tegra_pinctrl_soc_data tegra124_pinctrl = { @@ -1996,7 +2063,7 @@ static int tegra124_pinctrl_probe(struct platform_device *pdev) return tegra_pinctrl_probe(pdev, &tegra124_pinctrl); } -static struct of_device_id tegra124_pinctrl_of_match[] = { +static const struct of_device_id tegra124_pinctrl_of_match[] = { { .compatible = "nvidia,tegra124-pinmux", }, { }, }; diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c index 7563ebc9c791..c9805d2e71b0 100644 --- a/drivers/pinctrl/pinctrl-tegra20.c +++ b/drivers/pinctrl/pinctrl-tegra20.c @@ -2228,7 +2228,7 @@ static int tegra20_pinctrl_probe(struct platform_device *pdev) return tegra_pinctrl_probe(pdev, &tegra20_pinctrl); } -static struct of_device_id tegra20_pinctrl_of_match[] = { +static const struct of_device_id tegra20_pinctrl_of_match[] = { { .compatible = "nvidia,tegra20-pinmux", }, { }, }; diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c index fe2d2cf78ad9..e7b72e916558 100644 --- a/drivers/pinctrl/pinctrl-tegra30.c +++ b/drivers/pinctrl/pinctrl-tegra30.c @@ -2484,7 +2484,7 @@ static int tegra30_pinctrl_probe(struct platform_device *pdev) return tegra_pinctrl_probe(pdev, &tegra30_pinctrl); } -static struct of_device_id tegra30_pinctrl_of_match[] = { +static const struct of_device_id tegra30_pinctrl_of_match[] = { { .compatible = "nvidia,tegra30-pinmux", }, { }, }; diff --git a/drivers/pinctrl/pinctrl-tz1090-pdc.c b/drivers/pinctrl/pinctrl-tz1090-pdc.c index 41e81a35cabb..3bb6a3b78864 100644 --- a/drivers/pinctrl/pinctrl-tz1090-pdc.c +++ b/drivers/pinctrl/pinctrl-tz1090-pdc.c @@ -547,8 +547,9 @@ static void tz1090_pdc_pinctrl_mux(struct tz1090_pdc_pmx *pmx, __global_unlock2(flags); } -static int tz1090_pdc_pinctrl_enable(struct pinctrl_dev *pctldev, - unsigned int function, unsigned int group) +static int tz1090_pdc_pinctrl_set_mux(struct pinctrl_dev *pctldev, + unsigned int function, + unsigned int group) { struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); const struct tz1090_pdc_pingroup *grp = &tz1090_pdc_groups[group]; @@ -634,7 +635,7 @@ static struct pinmux_ops tz1090_pdc_pinmux_ops = { .get_functions_count = tz1090_pdc_pinctrl_get_funcs_count, .get_function_name = tz1090_pdc_pinctrl_get_func_name, .get_function_groups = tz1090_pdc_pinctrl_get_func_groups, - .enable = tz1090_pdc_pinctrl_enable, + .set_mux = tz1090_pdc_pinctrl_set_mux, .gpio_request_enable = tz1090_pdc_pinctrl_gpio_request_enable, .gpio_disable_free = tz1090_pdc_pinctrl_gpio_disable_free, }; diff --git a/drivers/pinctrl/pinctrl-tz1090.c b/drivers/pinctrl/pinctrl-tz1090.c index 24082216842e..48d36413b99f 100644 --- a/drivers/pinctrl/pinctrl-tz1090.c +++ b/drivers/pinctrl/pinctrl-tz1090.c @@ -1415,8 +1415,8 @@ found_mux: * the effect is the same as enabling the function on each individual pin in the * group. */ -static int tz1090_pinctrl_enable(struct pinctrl_dev *pctldev, - unsigned int function, unsigned int group) +static int tz1090_pinctrl_set_mux(struct pinctrl_dev *pctldev, + unsigned int function, unsigned int group) { struct tz1090_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); struct tz1090_pingroup *grp; @@ -1517,7 +1517,7 @@ static struct pinmux_ops tz1090_pinmux_ops = { .get_functions_count = tz1090_pinctrl_get_funcs_count, .get_function_name = tz1090_pinctrl_get_func_name, .get_function_groups = tz1090_pinctrl_get_func_groups, - .enable = tz1090_pinctrl_enable, + .set_mux = tz1090_pinctrl_set_mux, .gpio_request_enable = tz1090_pinctrl_gpio_request_enable, .gpio_disable_free = tz1090_pinctrl_gpio_disable_free, }; diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c index 0959bb36450f..e9c7113d81f2 100644 --- a/drivers/pinctrl/pinctrl-u300.c +++ b/drivers/pinctrl/pinctrl-u300.c @@ -955,8 +955,8 @@ static void u300_pmx_endisable(struct u300_pmx *upmx, unsigned selector, } } -static int u300_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group) +static int u300_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) { struct u300_pmx *upmx; @@ -994,7 +994,7 @@ static const struct pinmux_ops u300_pmx_ops = { .get_functions_count = u300_pmx_get_funcs_count, .get_function_name = u300_pmx_get_func_name, .get_function_groups = u300_pmx_get_groups, - .enable = u300_pmx_enable, + .set_mux = u300_pmx_set_mux, }; static int u300_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin, diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c index e66f4cae7633..37040ab42890 100644 --- a/drivers/pinctrl/pinctrl-xway.c +++ b/drivers/pinctrl/pinctrl-xway.c @@ -801,6 +801,7 @@ static int pinmux_xway_probe(struct platform_device *pdev) of_gpiochip_add(&xway_chip); ret = gpiochip_add(&xway_chip); if (ret) { + of_gpiochip_remove(&xway_chip); dev_err(&pdev->dev, "Failed to register gpio chip\n"); return ret; } @@ -822,6 +823,7 @@ static int pinmux_xway_probe(struct platform_device *pdev) /* register with the generic lantiq layer */ ret = ltq_pinctrl_register(pdev, &xway_info); if (ret) { + gpiochip_remove(&xway_chip); dev_err(&pdev->dev, "Failed to register pinctrl driver\n"); return ret; } diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index c055daf9a80f..b874458dcb88 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -41,7 +41,7 @@ int pinmux_check_ops(struct pinctrl_dev *pctldev) !ops->get_functions_count || !ops->get_function_name || !ops->get_function_groups || - !ops->enable) { + !ops->set_mux) { dev_err(pctldev->dev, "pinmux ops lacks necessary functions\n"); return -EINVAL; } @@ -445,15 +445,15 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting) desc->mux_setting = &(setting->data.mux); } - ret = ops->enable(pctldev, setting->data.mux.func, - setting->data.mux.group); + ret = ops->set_mux(pctldev, setting->data.mux.func, + setting->data.mux.group); if (ret) - goto err_enable; + goto err_set_mux; return 0; -err_enable: +err_set_mux: for (i = 0; i < num_pins; i++) { desc = pin_desc_get(pctldev, pins[i]); if (desc) diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index d160a710d704..81275af9638b 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -15,6 +15,14 @@ config PINCTRL_APQ8064 This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm TLMM block found in the Qualcomm APQ8064 platform. +config PINCTRL_APQ8084 + tristate "Qualcomm APQ8084 pin controller driver" + depends on GPIOLIB && OF + select PINCTRL_MSM + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm APQ8084 platform. + config PINCTRL_IPQ8064 tristate "Qualcomm IPQ8064 pin controller driver" depends on GPIOLIB && OF diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 2a02602d715c..ba8519fcd8d3 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -1,6 +1,7 @@ # Qualcomm pin control drivers obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o obj-$(CONFIG_PINCTRL_APQ8064) += pinctrl-apq8064.o +obj-$(CONFIG_PINCTRL_APQ8084) += pinctrl-apq8084.o obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o diff --git a/drivers/pinctrl/qcom/pinctrl-apq8064.c b/drivers/pinctrl/qcom/pinctrl-apq8064.c index feb6f152f9b7..c832d7d6b912 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8064.c @@ -258,6 +258,7 @@ static const unsigned int sdc3_data_pins[] = { 95 }; .intr_status_bit = 0, \ .intr_ack_high = 1, \ .intr_target_bit = 0, \ + .intr_target_kpss_val = 4, \ .intr_raw_status_bit = 3, \ .intr_polarity_bit = 1, \ .intr_detection_bit = 2, \ @@ -283,6 +284,7 @@ static const unsigned int sdc3_data_pins[] = { 95 }; .intr_enable_bit = -1, \ .intr_status_bit = -1, \ .intr_target_bit = -1, \ + .intr_target_kpss_val = -1, \ .intr_raw_status_bit = -1, \ .intr_polarity_bit = -1, \ .intr_detection_bit = -1, \ @@ -324,6 +326,7 @@ enum apq8064_functions { APQ_MUX_tsif1, APQ_MUX_tsif2, APQ_MUX_usb2_hsic, + APQ_MUX_ps_hold, APQ_MUX_NA, }; @@ -351,6 +354,9 @@ static const char * const gpio_groups[] = { "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89" }; +static const char * const ps_hold_groups[] = { + "gpio78" +}; static const char * const gsbi1_groups[] = { "gpio18", "gpio19", "gpio20", "gpio21" }; @@ -477,6 +483,7 @@ static const struct msm_function apq8064_functions[] = { FUNCTION(tsif1), FUNCTION(tsif2), FUNCTION(usb2_hsic), + FUNCTION(ps_hold), }; static const struct msm_pingroup apq8064_groups[] = { @@ -558,7 +565,7 @@ static const struct msm_pingroup apq8064_groups[] = { PINGROUP(75, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(76, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(77, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(78, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(78, ps_hold, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(79, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(80, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(81, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), diff --git a/drivers/pinctrl/qcom/pinctrl-apq8084.c b/drivers/pinctrl/qcom/pinctrl-apq8084.c new file mode 100644 index 000000000000..138cbf6134a5 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-apq8084.c @@ -0,0 +1,1245 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that 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. + * + */ + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pinctrl/pinctrl.h> + +#include "pinctrl-msm.h" + +static const struct pinctrl_pin_desc apq8084_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(104, "GPIO_104"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "GPIO_113"), + PINCTRL_PIN(114, "GPIO_114"), + PINCTRL_PIN(115, "GPIO_115"), + PINCTRL_PIN(116, "GPIO_116"), + PINCTRL_PIN(117, "GPIO_117"), + PINCTRL_PIN(118, "GPIO_118"), + PINCTRL_PIN(119, "GPIO_119"), + PINCTRL_PIN(120, "GPIO_120"), + PINCTRL_PIN(121, "GPIO_121"), + PINCTRL_PIN(122, "GPIO_122"), + PINCTRL_PIN(123, "GPIO_123"), + PINCTRL_PIN(124, "GPIO_124"), + PINCTRL_PIN(125, "GPIO_125"), + PINCTRL_PIN(126, "GPIO_126"), + PINCTRL_PIN(127, "GPIO_127"), + PINCTRL_PIN(128, "GPIO_128"), + PINCTRL_PIN(129, "GPIO_129"), + PINCTRL_PIN(130, "GPIO_130"), + PINCTRL_PIN(131, "GPIO_131"), + PINCTRL_PIN(132, "GPIO_132"), + PINCTRL_PIN(133, "GPIO_133"), + PINCTRL_PIN(134, "GPIO_134"), + PINCTRL_PIN(135, "GPIO_135"), + PINCTRL_PIN(136, "GPIO_136"), + PINCTRL_PIN(137, "GPIO_137"), + PINCTRL_PIN(138, "GPIO_138"), + PINCTRL_PIN(139, "GPIO_139"), + PINCTRL_PIN(140, "GPIO_140"), + PINCTRL_PIN(141, "GPIO_141"), + PINCTRL_PIN(142, "GPIO_142"), + PINCTRL_PIN(143, "GPIO_143"), + PINCTRL_PIN(144, "GPIO_144"), + PINCTRL_PIN(145, "GPIO_145"), + PINCTRL_PIN(146, "GPIO_146"), + + PINCTRL_PIN(147, "SDC1_CLK"), + PINCTRL_PIN(148, "SDC1_CMD"), + PINCTRL_PIN(149, "SDC1_DATA"), + PINCTRL_PIN(150, "SDC2_CLK"), + PINCTRL_PIN(151, "SDC2_CMD"), + PINCTRL_PIN(152, "SDC2_DATA"), +}; + +#define DECLARE_APQ_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin } + +DECLARE_APQ_GPIO_PINS(0); +DECLARE_APQ_GPIO_PINS(1); +DECLARE_APQ_GPIO_PINS(2); +DECLARE_APQ_GPIO_PINS(3); +DECLARE_APQ_GPIO_PINS(4); +DECLARE_APQ_GPIO_PINS(5); +DECLARE_APQ_GPIO_PINS(6); +DECLARE_APQ_GPIO_PINS(7); +DECLARE_APQ_GPIO_PINS(8); +DECLARE_APQ_GPIO_PINS(9); +DECLARE_APQ_GPIO_PINS(10); +DECLARE_APQ_GPIO_PINS(11); +DECLARE_APQ_GPIO_PINS(12); +DECLARE_APQ_GPIO_PINS(13); +DECLARE_APQ_GPIO_PINS(14); +DECLARE_APQ_GPIO_PINS(15); +DECLARE_APQ_GPIO_PINS(16); +DECLARE_APQ_GPIO_PINS(17); +DECLARE_APQ_GPIO_PINS(18); +DECLARE_APQ_GPIO_PINS(19); +DECLARE_APQ_GPIO_PINS(20); +DECLARE_APQ_GPIO_PINS(21); +DECLARE_APQ_GPIO_PINS(22); +DECLARE_APQ_GPIO_PINS(23); +DECLARE_APQ_GPIO_PINS(24); +DECLARE_APQ_GPIO_PINS(25); +DECLARE_APQ_GPIO_PINS(26); +DECLARE_APQ_GPIO_PINS(27); +DECLARE_APQ_GPIO_PINS(28); +DECLARE_APQ_GPIO_PINS(29); +DECLARE_APQ_GPIO_PINS(30); +DECLARE_APQ_GPIO_PINS(31); +DECLARE_APQ_GPIO_PINS(32); +DECLARE_APQ_GPIO_PINS(33); +DECLARE_APQ_GPIO_PINS(34); +DECLARE_APQ_GPIO_PINS(35); +DECLARE_APQ_GPIO_PINS(36); +DECLARE_APQ_GPIO_PINS(37); +DECLARE_APQ_GPIO_PINS(38); +DECLARE_APQ_GPIO_PINS(39); +DECLARE_APQ_GPIO_PINS(40); +DECLARE_APQ_GPIO_PINS(41); +DECLARE_APQ_GPIO_PINS(42); +DECLARE_APQ_GPIO_PINS(43); +DECLARE_APQ_GPIO_PINS(44); +DECLARE_APQ_GPIO_PINS(45); +DECLARE_APQ_GPIO_PINS(46); +DECLARE_APQ_GPIO_PINS(47); +DECLARE_APQ_GPIO_PINS(48); +DECLARE_APQ_GPIO_PINS(49); +DECLARE_APQ_GPIO_PINS(50); +DECLARE_APQ_GPIO_PINS(51); +DECLARE_APQ_GPIO_PINS(52); +DECLARE_APQ_GPIO_PINS(53); +DECLARE_APQ_GPIO_PINS(54); +DECLARE_APQ_GPIO_PINS(55); +DECLARE_APQ_GPIO_PINS(56); +DECLARE_APQ_GPIO_PINS(57); +DECLARE_APQ_GPIO_PINS(58); +DECLARE_APQ_GPIO_PINS(59); +DECLARE_APQ_GPIO_PINS(60); +DECLARE_APQ_GPIO_PINS(61); +DECLARE_APQ_GPIO_PINS(62); +DECLARE_APQ_GPIO_PINS(63); +DECLARE_APQ_GPIO_PINS(64); +DECLARE_APQ_GPIO_PINS(65); +DECLARE_APQ_GPIO_PINS(66); +DECLARE_APQ_GPIO_PINS(67); +DECLARE_APQ_GPIO_PINS(68); +DECLARE_APQ_GPIO_PINS(69); +DECLARE_APQ_GPIO_PINS(70); +DECLARE_APQ_GPIO_PINS(71); +DECLARE_APQ_GPIO_PINS(72); +DECLARE_APQ_GPIO_PINS(73); +DECLARE_APQ_GPIO_PINS(74); +DECLARE_APQ_GPIO_PINS(75); +DECLARE_APQ_GPIO_PINS(76); +DECLARE_APQ_GPIO_PINS(77); +DECLARE_APQ_GPIO_PINS(78); +DECLARE_APQ_GPIO_PINS(79); +DECLARE_APQ_GPIO_PINS(80); +DECLARE_APQ_GPIO_PINS(81); +DECLARE_APQ_GPIO_PINS(82); +DECLARE_APQ_GPIO_PINS(83); +DECLARE_APQ_GPIO_PINS(84); +DECLARE_APQ_GPIO_PINS(85); +DECLARE_APQ_GPIO_PINS(86); +DECLARE_APQ_GPIO_PINS(87); +DECLARE_APQ_GPIO_PINS(88); +DECLARE_APQ_GPIO_PINS(89); +DECLARE_APQ_GPIO_PINS(90); +DECLARE_APQ_GPIO_PINS(91); +DECLARE_APQ_GPIO_PINS(92); +DECLARE_APQ_GPIO_PINS(93); +DECLARE_APQ_GPIO_PINS(94); +DECLARE_APQ_GPIO_PINS(95); +DECLARE_APQ_GPIO_PINS(96); +DECLARE_APQ_GPIO_PINS(97); +DECLARE_APQ_GPIO_PINS(98); +DECLARE_APQ_GPIO_PINS(99); +DECLARE_APQ_GPIO_PINS(100); +DECLARE_APQ_GPIO_PINS(101); +DECLARE_APQ_GPIO_PINS(102); +DECLARE_APQ_GPIO_PINS(103); +DECLARE_APQ_GPIO_PINS(104); +DECLARE_APQ_GPIO_PINS(105); +DECLARE_APQ_GPIO_PINS(106); +DECLARE_APQ_GPIO_PINS(107); +DECLARE_APQ_GPIO_PINS(108); +DECLARE_APQ_GPIO_PINS(109); +DECLARE_APQ_GPIO_PINS(110); +DECLARE_APQ_GPIO_PINS(111); +DECLARE_APQ_GPIO_PINS(112); +DECLARE_APQ_GPIO_PINS(113); +DECLARE_APQ_GPIO_PINS(114); +DECLARE_APQ_GPIO_PINS(115); +DECLARE_APQ_GPIO_PINS(116); +DECLARE_APQ_GPIO_PINS(117); +DECLARE_APQ_GPIO_PINS(118); +DECLARE_APQ_GPIO_PINS(119); +DECLARE_APQ_GPIO_PINS(120); +DECLARE_APQ_GPIO_PINS(121); +DECLARE_APQ_GPIO_PINS(122); +DECLARE_APQ_GPIO_PINS(123); +DECLARE_APQ_GPIO_PINS(124); +DECLARE_APQ_GPIO_PINS(125); +DECLARE_APQ_GPIO_PINS(126); +DECLARE_APQ_GPIO_PINS(127); +DECLARE_APQ_GPIO_PINS(128); +DECLARE_APQ_GPIO_PINS(129); +DECLARE_APQ_GPIO_PINS(130); +DECLARE_APQ_GPIO_PINS(131); +DECLARE_APQ_GPIO_PINS(132); +DECLARE_APQ_GPIO_PINS(133); +DECLARE_APQ_GPIO_PINS(134); +DECLARE_APQ_GPIO_PINS(135); +DECLARE_APQ_GPIO_PINS(136); +DECLARE_APQ_GPIO_PINS(137); +DECLARE_APQ_GPIO_PINS(138); +DECLARE_APQ_GPIO_PINS(139); +DECLARE_APQ_GPIO_PINS(140); +DECLARE_APQ_GPIO_PINS(141); +DECLARE_APQ_GPIO_PINS(142); +DECLARE_APQ_GPIO_PINS(143); +DECLARE_APQ_GPIO_PINS(144); +DECLARE_APQ_GPIO_PINS(145); +DECLARE_APQ_GPIO_PINS(146); + +static const unsigned int sdc1_clk_pins[] = { 147 }; +static const unsigned int sdc1_cmd_pins[] = { 148 }; +static const unsigned int sdc1_data_pins[] = { 149 }; +static const unsigned int sdc2_clk_pins[] = { 150 }; +static const unsigned int sdc2_cmd_pins[] = { 151 }; +static const unsigned int sdc2_data_pins[] = { 152 }; + +#define FUNCTION(fname) \ + [APQ_MUX_##fname] = { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ + { \ + .name = "gpio" #id, \ + .pins = gpio##id##_pins, \ + .npins = ARRAY_SIZE(gpio##id##_pins), \ + .funcs = (int[]){ \ + APQ_MUX_gpio, \ + APQ_MUX_##f1, \ + APQ_MUX_##f2, \ + APQ_MUX_##f3, \ + APQ_MUX_##f4, \ + APQ_MUX_##f5, \ + APQ_MUX_##f6, \ + APQ_MUX_##f7 \ + }, \ + .nfuncs = 8, \ + .ctl_reg = 0x1000 + 0x10 * id, \ + .io_reg = 0x1004 + 0x10 * id, \ + .intr_cfg_reg = 0x1008 + 0x10 * id, \ + .intr_status_reg = 0x100c + 0x10 * id, \ + .intr_target_reg = 0x1008 + 0x10 * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_ack_high = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 3, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +#define SDC_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_target_kpss_val = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } + +enum apq8084_functions { + APQ_MUX_adsp_ext, + APQ_MUX_audio_ref, + APQ_MUX_blsp_i2c1, + APQ_MUX_blsp_i2c2, + APQ_MUX_blsp_i2c3, + APQ_MUX_blsp_i2c4, + APQ_MUX_blsp_i2c5, + APQ_MUX_blsp_i2c6, + APQ_MUX_blsp_i2c7, + APQ_MUX_blsp_i2c8, + APQ_MUX_blsp_i2c9, + APQ_MUX_blsp_i2c10, + APQ_MUX_blsp_i2c11, + APQ_MUX_blsp_i2c12, + APQ_MUX_blsp_spi1, + APQ_MUX_blsp_spi1_cs1, + APQ_MUX_blsp_spi1_cs2, + APQ_MUX_blsp_spi1_cs3, + APQ_MUX_blsp_spi2, + APQ_MUX_blsp_spi3, + APQ_MUX_blsp_spi3_cs1, + APQ_MUX_blsp_spi3_cs2, + APQ_MUX_blsp_spi3_cs3, + APQ_MUX_blsp_spi4, + APQ_MUX_blsp_spi5, + APQ_MUX_blsp_spi6, + APQ_MUX_blsp_spi7, + APQ_MUX_blsp_spi8, + APQ_MUX_blsp_spi9, + APQ_MUX_blsp_spi10, + APQ_MUX_blsp_spi10_cs1, + APQ_MUX_blsp_spi10_cs2, + APQ_MUX_blsp_spi10_cs3, + APQ_MUX_blsp_spi11, + APQ_MUX_blsp_spi12, + APQ_MUX_blsp_uart1, + APQ_MUX_blsp_uart2, + APQ_MUX_blsp_uart3, + APQ_MUX_blsp_uart4, + APQ_MUX_blsp_uart5, + APQ_MUX_blsp_uart6, + APQ_MUX_blsp_uart7, + APQ_MUX_blsp_uart8, + APQ_MUX_blsp_uart9, + APQ_MUX_blsp_uart10, + APQ_MUX_blsp_uart11, + APQ_MUX_blsp_uart12, + APQ_MUX_blsp_uim1, + APQ_MUX_blsp_uim2, + APQ_MUX_blsp_uim3, + APQ_MUX_blsp_uim4, + APQ_MUX_blsp_uim5, + APQ_MUX_blsp_uim6, + APQ_MUX_blsp_uim7, + APQ_MUX_blsp_uim8, + APQ_MUX_blsp_uim9, + APQ_MUX_blsp_uim10, + APQ_MUX_blsp_uim11, + APQ_MUX_blsp_uim12, + APQ_MUX_cam_mclk0, + APQ_MUX_cam_mclk1, + APQ_MUX_cam_mclk2, + APQ_MUX_cam_mclk3, + APQ_MUX_cci_async, + APQ_MUX_cci_async_in0, + APQ_MUX_cci_i2c0, + APQ_MUX_cci_i2c1, + APQ_MUX_cci_timer0, + APQ_MUX_cci_timer1, + APQ_MUX_cci_timer2, + APQ_MUX_cci_timer3, + APQ_MUX_cci_timer4, + APQ_MUX_edp_hpd, + APQ_MUX_gcc_gp1, + APQ_MUX_gcc_gp2, + APQ_MUX_gcc_gp3, + APQ_MUX_gcc_obt, + APQ_MUX_gcc_vtt, + APQ_MUX_gp_mn, + APQ_MUX_gp_pdm0, + APQ_MUX_gp_pdm1, + APQ_MUX_gp_pdm2, + APQ_MUX_gp0_clk, + APQ_MUX_gp1_clk, + APQ_MUX_gpio, + APQ_MUX_hdmi_cec, + APQ_MUX_hdmi_ddc, + APQ_MUX_hdmi_dtest, + APQ_MUX_hdmi_hpd, + APQ_MUX_hdmi_rcv, + APQ_MUX_hsic, + APQ_MUX_ldo_en, + APQ_MUX_ldo_update, + APQ_MUX_mdp_vsync, + APQ_MUX_pci_e0, + APQ_MUX_pci_e0_n, + APQ_MUX_pci_e0_rst, + APQ_MUX_pci_e1, + APQ_MUX_pci_e1_rst, + APQ_MUX_pci_e1_rst_n, + APQ_MUX_pci_e1_clkreq_n, + APQ_MUX_pri_mi2s, + APQ_MUX_qua_mi2s, + APQ_MUX_sata_act, + APQ_MUX_sata_devsleep, + APQ_MUX_sata_devsleep_n, + APQ_MUX_sd_write, + APQ_MUX_sdc_emmc_mode, + APQ_MUX_sdc3, + APQ_MUX_sdc4, + APQ_MUX_sec_mi2s, + APQ_MUX_slimbus, + APQ_MUX_spdif_tx, + APQ_MUX_spkr_i2s, + APQ_MUX_spkr_i2s_ws, + APQ_MUX_spss_geni, + APQ_MUX_ter_mi2s, + APQ_MUX_tsif1, + APQ_MUX_tsif2, + APQ_MUX_uim, + APQ_MUX_uim_batt_alarm, + APQ_MUX_NA, +}; + +static const char * const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", + "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", + "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", + "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", + "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", + "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", + "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84", + "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91", + "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98", + "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104", + "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110", + "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116", + "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122", + "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128", + "gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134", + "gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140", + "gpio141", "gpio142", "gpio143", "gpio144", "gpio145", "gpio146" +}; + +static const char * const adsp_ext_groups[] = { + "gpio34" +}; +static const char * const audio_ref_groups[] = { + "gpio100" +}; +static const char * const blsp_i2c1_groups[] = { + "gpio2", "gpio3" +}; +static const char * const blsp_i2c2_groups[] = { + "gpio6", "gpio7" +}; +static const char * const blsp_i2c3_groups[] = { + "gpio10", "gpio11" +}; +static const char * const blsp_i2c4_groups[] = { + "gpio29", "gpio30" +}; +static const char * const blsp_i2c5_groups[] = { + "gpio41", "gpio42" +}; +static const char * const blsp_i2c6_groups[] = { + "gpio45", "gpio46" +}; +static const char * const blsp_i2c7_groups[] = { + "gpio132", "gpio133" +}; +static const char * const blsp_i2c8_groups[] = { + "gpio53", "gpio54" +}; +static const char * const blsp_i2c9_groups[] = { + "gpio57", "gpio58" +}; +static const char * const blsp_i2c10_groups[] = { + "gpio61", "gpio62" +}; +static const char * const blsp_i2c11_groups[] = { + "gpio65", "gpio66" +}; +static const char * const blsp_i2c12_groups[] = { + "gpio49", "gpio50" +}; +static const char * const blsp_spi1_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3" +}; +static const char * const blsp_spi2_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7" +}; +static const char * const blsp_spi3_groups[] = { + "gpio8", "gpio9", "gpio10", "gpio11" +}; +static const char * const blsp_spi4_groups[] = { + "gpio27", "gpio28", "gpio29", "gpio30" +}; +static const char * const blsp_spi5_groups[] = { + "gpio39", "gpio40", "gpio41", "gpio42" +}; +static const char * const blsp_spi6_groups[] = { + "gpio43", "gpio44", "gpio45", "gpio46" +}; +static const char * const blsp_spi7_groups[] = { + "gpio130", "gpio131", "gpio132", "gpio133" +}; +static const char * const blsp_spi8_groups[] = { + "gpio51", "gpio52", "gpio53", "gpio54" +}; +static const char * const blsp_spi9_groups[] = { + "gpio55", "gpio56", "gpio57", "gpio58" +}; +static const char * const blsp_spi10_groups[] = { + "gpio59", "gpio60", "gpio61", "gpio62" +}; +static const char * const blsp_spi11_groups[] = { + "gpio63", "gpio64", "gpio65", "gpio66" +}; +static const char * const blsp_spi12_groups[] = { + "gpio47", "gpio48", "gpio49", "gpio50" +}; +static const char * const blsp_uart1_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3" +}; +static const char * const blsp_uart2_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7" +}; +static const char * const blsp_uart3_groups[] = { + "gpio8" +}; +static const char * const blsp_uart4_groups[] = { + "gpio27", "gpio28", "gpio29", "gpio30" +}; +static const char * const blsp_uart5_groups[] = { + "gpio39", "gpio40", "gpio41", "gpio42" +}; +static const char * const blsp_uart6_groups[] = { + "gpio43", "gpio44", "gpio45", "gpio46" +}; +static const char * const blsp_uart7_groups[] = { + "gpio130", "gpio131", "gpio132", "gpio133" +}; +static const char * const blsp_uart8_groups[] = { + "gpio51", "gpio52", "gpio53", "gpio54" +}; +static const char * const blsp_uart9_groups[] = { + "gpio55", "gpio56", "gpio57", "gpio58" +}; +static const char * const blsp_uart10_groups[] = { + "gpio59", "gpio60", "gpio61", "gpio62" +}; +static const char * const blsp_uart11_groups[] = { + "gpio63", "gpio64", "gpio65", "gpio66" +}; +static const char * const blsp_uart12_groups[] = { + "gpio47", "gpio48", "gpio49", "gpio50" +}; +static const char * const blsp_uim1_groups[] = { + "gpio0", "gpio1" +}; +static const char * const blsp_uim2_groups[] = { + "gpio4", "gpio5" +}; +static const char * const blsp_uim3_groups[] = { + "gpio8", "gpio9" +}; +static const char * const blsp_uim4_groups[] = { + "gpio27", "gpio28" +}; +static const char * const blsp_uim5_groups[] = { + "gpio39", "gpio40" +}; +static const char * const blsp_uim6_groups[] = { + "gpio43", "gpio44" +}; +static const char * const blsp_uim7_groups[] = { + "gpio130", "gpio131" +}; +static const char * const blsp_uim8_groups[] = { + "gpio51", "gpio52" +}; +static const char * const blsp_uim9_groups[] = { + "gpio55", "gpio56" +}; +static const char * const blsp_uim10_groups[] = { + "gpio59", "gpio60" +}; +static const char * const blsp_uim11_groups[] = { + "gpio63", "gpio64" +}; +static const char * const blsp_uim12_groups[] = { + "gpio47", "gpio48" +}; +static const char * const blsp_spi1_cs1_groups[] = { + "gpio116" +}; +static const char * const blsp_spi1_cs2_groups[] = { + "gpio117" +}; +static const char * const blsp_spi1_cs3_groups[] = { + "gpio118" +}; +static const char * const blsp_spi3_cs1_groups[] = { + "gpio67" +}; +static const char * const blsp_spi3_cs2_groups[] = { + "gpio71" +}; +static const char * const blsp_spi3_cs3_groups[] = { + "gpio72" +}; +static const char * const blsp_spi10_cs1_groups[] = { + "gpio106" +}; +static const char * const blsp_spi10_cs2_groups[] = { + "gpio111" +}; +static const char * const blsp_spi10_cs3_groups[] = { + "gpio128" +}; +static const char * const cam_mclk0_groups[] = { + "gpio15" +}; +static const char * const cam_mclk1_groups[] = { + "gpio16" +}; +static const char * const cam_mclk2_groups[] = { + "gpio17" +}; +static const char * const cam_mclk3_groups[] = { + "gpio18" +}; +static const char * const cci_async_groups[] = { + "gpio26", "gpio119" +}; +static const char * const cci_async_in0_groups[] = { + "gpio120" +}; +static const char * const cci_i2c0_groups[] = { + "gpio19", "gpio20" +}; +static const char * const cci_i2c1_groups[] = { + "gpio21", "gpio22" +}; +static const char * const cci_timer0_groups[] = { + "gpio23" +}; +static const char * const cci_timer1_groups[] = { + "gpio24" +}; +static const char * const cci_timer2_groups[] = { + "gpio25" +}; +static const char * const cci_timer3_groups[] = { + "gpio26" +}; +static const char * const cci_timer4_groups[] = { + "gpio119" +}; +static const char * const edp_hpd_groups[] = { + "gpio103" +}; +static const char * const gcc_gp1_groups[] = { + "gpio37" +}; +static const char * const gcc_gp2_groups[] = { + "gpio38" +}; +static const char * const gcc_gp3_groups[] = { + "gpio86" +}; +static const char * const gcc_obt_groups[] = { + "gpio127" +}; +static const char * const gcc_vtt_groups[] = { + "gpio126" +}; +static const char * const gp_mn_groups[] = { + "gpio29" +}; +static const char * const gp_pdm0_groups[] = { + "gpio48", "gpio83" +}; +static const char * const gp_pdm1_groups[] = { + "gpio84", "gpio101" +}; +static const char * const gp_pdm2_groups[] = { + "gpio85", "gpio110" +}; +static const char * const gp0_clk_groups[] = { + "gpio25" +}; +static const char * const gp1_clk_groups[] = { + "gpio26" +}; +static const char * const hdmi_cec_groups[] = { + "gpio31" +}; +static const char * const hdmi_ddc_groups[] = { + "gpio32", "gpio33" +}; +static const char * const hdmi_dtest_groups[] = { + "gpio123" +}; +static const char * const hdmi_hpd_groups[] = { + "gpio34" +}; +static const char * const hdmi_rcv_groups[] = { + "gpio125" +}; +static const char * const hsic_groups[] = { + "gpio134", "gpio135" +}; +static const char * const ldo_en_groups[] = { + "gpio124" +}; +static const char * const ldo_update_groups[] = { + "gpio125" +}; +static const char * const mdp_vsync_groups[] = { + "gpio12", "gpio13", "gpio14" +}; +static const char * const pci_e0_groups[] = { + "gpio68", "gpio70" +}; +static const char * const pci_e0_n_groups[] = { + "gpio68", "gpio70" +}; +static const char * const pci_e0_rst_groups[] = { + "gpio70" +}; +static const char * const pci_e1_groups[] = { + "gpio140" +}; +static const char * const pci_e1_rst_groups[] = { + "gpio140" +}; +static const char * const pci_e1_rst_n_groups[] = { + "gpio140" +}; +static const char * const pci_e1_clkreq_n_groups[] = { + "gpio141" +}; +static const char * const pri_mi2s_groups[] = { + "gpio76", "gpio77", "gpio78", "gpio79", "gpio80" +}; +static const char * const qua_mi2s_groups[] = { + "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97" +}; +static const char * const sata_act_groups[] = { + "gpio129" +}; +static const char * const sata_devsleep_groups[] = { + "gpio119" +}; +static const char * const sata_devsleep_n_groups[] = { + "gpio119" +}; +static const char * const sd_write_groups[] = { + "gpio75" +}; +static const char * const sdc_emmc_mode_groups[] = { + "gpio146" +}; +static const char * const sdc3_groups[] = { + "gpio67", "gpio68", "gpio69", "gpio70", "gpio71", "gpio72" +}; +static const char * const sdc4_groups[] = { + "gpio82", "gpio83", "gpio84", "gpio85", "gpio86", + "gpio91", "gpio95", "gpio96", "gpio97", "gpio101" +}; +static const char * const sec_mi2s_groups[] = { + "gpio81", "gpio82", "gpio83", "gpio84", "gpio85" +}; +static const char * const slimbus_groups[] = { + "gpio98", "gpio99" +}; +static const char * const spdif_tx_groups[] = { + "gpio124", "gpio136", "gpio142" +}; +static const char * const spkr_i2s_groups[] = { + "gpio98", "gpio99", "gpio100" +}; +static const char * const spkr_i2s_ws_groups[] = { + "gpio104" +}; +static const char * const spss_geni_groups[] = { + "gpio8", "gpio9" +}; +static const char * const ter_mi2s_groups[] = { + "gpio86", "gpio87", "gpio88", "gpio89", "gpio90" +}; +static const char * const tsif1_groups[] = { + "gpio82", "gpio83", "gpio84", "gpio85", "gpio86" +}; +static const char * const tsif2_groups[] = { + "gpio91", "gpio95", "gpio96", "gpio97", "gpio101" +}; +static const char * const uim_groups[] = { + "gpio130", "gpio131", "gpio132", "gpio133" +}; +static const char * const uim_batt_alarm_groups[] = { + "gpio102" +}; +static const struct msm_function apq8084_functions[] = { + FUNCTION(adsp_ext), + FUNCTION(audio_ref), + FUNCTION(blsp_i2c1), + FUNCTION(blsp_i2c2), + FUNCTION(blsp_i2c3), + FUNCTION(blsp_i2c4), + FUNCTION(blsp_i2c5), + FUNCTION(blsp_i2c6), + FUNCTION(blsp_i2c7), + FUNCTION(blsp_i2c8), + FUNCTION(blsp_i2c9), + FUNCTION(blsp_i2c10), + FUNCTION(blsp_i2c11), + FUNCTION(blsp_i2c12), + FUNCTION(blsp_spi1), + FUNCTION(blsp_spi1_cs1), + FUNCTION(blsp_spi1_cs2), + FUNCTION(blsp_spi1_cs3), + FUNCTION(blsp_spi2), + FUNCTION(blsp_spi3), + FUNCTION(blsp_spi3_cs1), + FUNCTION(blsp_spi3_cs2), + FUNCTION(blsp_spi3_cs3), + FUNCTION(blsp_spi4), + FUNCTION(blsp_spi5), + FUNCTION(blsp_spi6), + FUNCTION(blsp_spi7), + FUNCTION(blsp_spi8), + FUNCTION(blsp_spi9), + FUNCTION(blsp_spi10), + FUNCTION(blsp_spi10_cs1), + FUNCTION(blsp_spi10_cs2), + FUNCTION(blsp_spi10_cs3), + FUNCTION(blsp_spi11), + FUNCTION(blsp_spi12), + FUNCTION(blsp_uart1), + FUNCTION(blsp_uart2), + FUNCTION(blsp_uart3), + FUNCTION(blsp_uart4), + FUNCTION(blsp_uart5), + FUNCTION(blsp_uart6), + FUNCTION(blsp_uart7), + FUNCTION(blsp_uart8), + FUNCTION(blsp_uart9), + FUNCTION(blsp_uart10), + FUNCTION(blsp_uart11), + FUNCTION(blsp_uart12), + FUNCTION(blsp_uim1), + FUNCTION(blsp_uim2), + FUNCTION(blsp_uim3), + FUNCTION(blsp_uim4), + FUNCTION(blsp_uim5), + FUNCTION(blsp_uim6), + FUNCTION(blsp_uim7), + FUNCTION(blsp_uim8), + FUNCTION(blsp_uim9), + FUNCTION(blsp_uim10), + FUNCTION(blsp_uim11), + FUNCTION(blsp_uim12), + FUNCTION(cam_mclk0), + FUNCTION(cam_mclk1), + FUNCTION(cam_mclk2), + FUNCTION(cam_mclk3), + FUNCTION(cci_async), + FUNCTION(cci_async_in0), + FUNCTION(cci_i2c0), + FUNCTION(cci_i2c1), + FUNCTION(cci_timer0), + FUNCTION(cci_timer1), + FUNCTION(cci_timer2), + FUNCTION(cci_timer3), + FUNCTION(cci_timer4), + FUNCTION(edp_hpd), + FUNCTION(gcc_gp1), + FUNCTION(gcc_gp2), + FUNCTION(gcc_gp3), + FUNCTION(gcc_obt), + FUNCTION(gcc_vtt), + FUNCTION(gp_mn), + FUNCTION(gp_pdm0), + FUNCTION(gp_pdm1), + FUNCTION(gp_pdm2), + FUNCTION(gp0_clk), + FUNCTION(gp1_clk), + FUNCTION(gpio), + FUNCTION(hdmi_cec), + FUNCTION(hdmi_ddc), + FUNCTION(hdmi_dtest), + FUNCTION(hdmi_hpd), + FUNCTION(hdmi_rcv), + FUNCTION(hsic), + FUNCTION(ldo_en), + FUNCTION(ldo_update), + FUNCTION(mdp_vsync), + FUNCTION(pci_e0), + FUNCTION(pci_e0_n), + FUNCTION(pci_e0_rst), + FUNCTION(pci_e1), + FUNCTION(pci_e1_rst), + FUNCTION(pci_e1_rst_n), + FUNCTION(pci_e1_clkreq_n), + FUNCTION(pri_mi2s), + FUNCTION(qua_mi2s), + FUNCTION(sata_act), + FUNCTION(sata_devsleep), + FUNCTION(sata_devsleep_n), + FUNCTION(sd_write), + FUNCTION(sdc_emmc_mode), + FUNCTION(sdc3), + FUNCTION(sdc4), + FUNCTION(sec_mi2s), + FUNCTION(slimbus), + FUNCTION(spdif_tx), + FUNCTION(spkr_i2s), + FUNCTION(spkr_i2s_ws), + FUNCTION(spss_geni), + FUNCTION(ter_mi2s), + FUNCTION(tsif1), + FUNCTION(tsif2), + FUNCTION(uim), + FUNCTION(uim_batt_alarm), +}; + +static const struct msm_pingroup apq8084_groups[] = { + PINGROUP(0, blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA), + PINGROUP(1, blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA), + PINGROUP(2, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA), + PINGROUP(3, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA), + PINGROUP(4, blsp_spi2, blsp_uart2, blsp_uim2, NA, NA, NA, NA), + PINGROUP(5, blsp_spi2, blsp_uart2, blsp_uim2, NA, NA, NA, NA), + PINGROUP(6, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA), + PINGROUP(7, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA), + PINGROUP(8, blsp_spi3, blsp_uart3, blsp_uim3, spss_geni, NA, NA, NA), + PINGROUP(9, blsp_spi3, blsp_uim3, blsp_uart3, spss_geni, NA, NA, NA), + PINGROUP(10, blsp_spi3, blsp_uart3, blsp_i2c3, NA, NA, NA, NA), + PINGROUP(11, blsp_spi3, blsp_uart3, blsp_i2c3, NA, NA, NA, NA), + PINGROUP(12, mdp_vsync, NA, NA, NA, NA, NA, NA), + PINGROUP(13, mdp_vsync, NA, NA, NA, NA, NA, NA), + PINGROUP(14, mdp_vsync, NA, NA, NA, NA, NA, NA), + PINGROUP(15, cam_mclk0, NA, NA, NA, NA, NA, NA), + PINGROUP(16, cam_mclk1, NA, NA, NA, NA, NA, NA), + PINGROUP(17, cam_mclk2, NA, NA, NA, NA, NA, NA), + PINGROUP(18, cam_mclk3, NA, NA, NA, NA, NA, NA), + PINGROUP(19, cci_i2c0, NA, NA, NA, NA, NA, NA), + PINGROUP(20, cci_i2c0, NA, NA, NA, NA, NA, NA), + PINGROUP(21, cci_i2c1, NA, NA, NA, NA, NA, NA), + PINGROUP(22, cci_i2c1, NA, NA, NA, NA, NA, NA), + PINGROUP(23, cci_timer0, NA, NA, NA, NA, NA, NA), + PINGROUP(24, cci_timer1, NA, NA, NA, NA, NA, NA), + PINGROUP(25, cci_timer2, gp0_clk, NA, NA, NA, NA, NA), + PINGROUP(26, cci_timer3, cci_async, gp1_clk, NA, NA, NA, NA), + PINGROUP(27, blsp_spi4, blsp_uart4, blsp_uim4, NA, NA, NA, NA), + PINGROUP(28, blsp_spi4, blsp_uart4, blsp_uim4, NA, NA, NA, NA), + PINGROUP(29, blsp_spi4, blsp_uart4, blsp_i2c4, gp_mn, NA, NA, NA), + PINGROUP(30, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA, NA), + PINGROUP(31, hdmi_cec, NA, NA, NA, NA, NA, NA), + PINGROUP(32, hdmi_ddc, NA, NA, NA, NA, NA, NA), + PINGROUP(33, hdmi_ddc, NA, NA, NA, NA, NA, NA), + PINGROUP(34, hdmi_hpd, NA, adsp_ext, NA, NA, NA, NA), + PINGROUP(35, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(36, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(37, gcc_gp1, NA, NA, NA, NA, NA, NA), + PINGROUP(38, gcc_gp2, NA, NA, NA, NA, NA, NA), + PINGROUP(39, blsp_spi5, blsp_uart5, blsp_uim5, NA, NA, NA, NA), + PINGROUP(40, blsp_spi5, blsp_uart5, blsp_uim5, NA, NA, NA, NA), + PINGROUP(41, blsp_spi5, blsp_uart5, blsp_i2c5, NA, NA, NA, NA), + PINGROUP(42, blsp_spi5, blsp_uart5, blsp_i2c5, NA, NA, NA, NA), + PINGROUP(43, blsp_spi6, blsp_uart6, blsp_uim6, NA, NA, NA, NA), + PINGROUP(44, blsp_spi6, blsp_uart6, blsp_uim6, NA, NA, NA, NA), + PINGROUP(45, blsp_spi6, blsp_uart6, blsp_i2c6, NA, NA, NA, NA), + PINGROUP(46, blsp_spi6, blsp_uart6, blsp_i2c6, NA, NA, NA, NA), + PINGROUP(47, blsp_spi12, blsp_uart12, blsp_uim12, NA, NA, NA, NA), + PINGROUP(48, blsp_spi12, blsp_uart12, blsp_uim12, gp_pdm0, NA, NA, NA), + PINGROUP(49, blsp_spi12, blsp_uart12, blsp_i2c12, NA, NA, NA, NA), + PINGROUP(50, blsp_spi12, blsp_uart12, blsp_i2c12, NA, NA, NA, NA), + PINGROUP(51, blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA), + PINGROUP(52, blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA), + PINGROUP(53, blsp_spi8, blsp_uart8, blsp_i2c8, NA, NA, NA, NA), + PINGROUP(54, blsp_spi8, blsp_uart8, blsp_i2c8, NA, NA, NA, NA), + PINGROUP(55, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA), + PINGROUP(56, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA), + PINGROUP(57, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA), + PINGROUP(58, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA), + PINGROUP(59, blsp_spi10, blsp_uart10, blsp_uim10, NA, NA, NA, NA), + PINGROUP(60, blsp_spi10, blsp_uart10, blsp_uim10, NA, NA, NA, NA), + PINGROUP(61, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA, NA), + PINGROUP(62, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA, NA), + PINGROUP(63, blsp_spi11, blsp_uart11, blsp_uim11, NA, NA, NA, NA), + PINGROUP(64, blsp_spi11, blsp_uart11, blsp_uim11, NA, NA, NA, NA), + PINGROUP(65, blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA), + PINGROUP(66, blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA), + PINGROUP(67, sdc3, blsp_spi3_cs1, NA, NA, NA, NA, NA), + PINGROUP(68, sdc3, pci_e0, NA, NA, NA, NA, NA), + PINGROUP(69, sdc3, NA, NA, NA, NA, NA, NA), + PINGROUP(70, sdc3, pci_e0_n, pci_e0, NA, NA, NA, NA), + PINGROUP(71, sdc3, blsp_spi3_cs2, NA, NA, NA, NA, NA), + PINGROUP(72, sdc3, blsp_spi3_cs3, NA, NA, NA, NA, NA), + PINGROUP(73, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(74, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(75, sd_write, NA, NA, NA, NA, NA, NA), + PINGROUP(76, pri_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(77, pri_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(78, pri_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(79, pri_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(80, pri_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(81, sec_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(82, sec_mi2s, sdc4, tsif1, NA, NA, NA, NA), + PINGROUP(83, sec_mi2s, sdc4, tsif1, NA, NA, NA, gp_pdm0), + PINGROUP(84, sec_mi2s, sdc4, tsif1, NA, NA, NA, gp_pdm1), + PINGROUP(85, sec_mi2s, sdc4, tsif1, NA, gp_pdm2, NA, NA), + PINGROUP(86, ter_mi2s, sdc4, tsif1, NA, NA, NA, gcc_gp3), + PINGROUP(87, ter_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(88, ter_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(89, ter_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(90, ter_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(91, qua_mi2s, sdc4, tsif2, NA, NA, NA, NA), + PINGROUP(92, qua_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(93, qua_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(94, qua_mi2s, NA, NA, NA, NA, NA, NA), + PINGROUP(95, qua_mi2s, sdc4, tsif2, NA, NA, NA, gcc_gp1), + PINGROUP(96, qua_mi2s, sdc4, tsif2, NA, NA, NA, gcc_gp2), + PINGROUP(97, qua_mi2s, sdc4, tsif2, NA, gcc_gp3, NA, NA), + PINGROUP(98, slimbus, spkr_i2s, NA, NA, NA, NA, NA), + PINGROUP(99, slimbus, spkr_i2s, NA, NA, NA, NA, NA), + PINGROUP(100, audio_ref, spkr_i2s, NA, NA, NA, NA, NA), + PINGROUP(101, sdc4, tsif2, gp_pdm1, NA, NA, NA, NA), + PINGROUP(102, uim_batt_alarm, NA, NA, NA, NA, NA, NA), + PINGROUP(103, edp_hpd, NA, NA, NA, NA, NA, NA), + PINGROUP(104, spkr_i2s, NA, NA, NA, NA, NA, NA), + PINGROUP(105, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(106, blsp_spi10_cs1, NA, NA, NA, NA, NA, NA), + PINGROUP(107, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(108, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(109, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(110, gp_pdm2, NA, NA, NA, NA, NA, NA), + PINGROUP(111, blsp_spi10_cs2, NA, NA, NA, NA, NA, NA), + PINGROUP(112, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(113, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(114, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(115, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(116, blsp_spi1_cs1, NA, NA, NA, NA, NA, NA), + PINGROUP(117, blsp_spi1_cs2, NA, NA, NA, NA, NA, NA), + PINGROUP(118, blsp_spi1_cs3, NA, NA, NA, NA, NA, NA), + PINGROUP(119, cci_timer4, cci_async, sata_devsleep, sata_devsleep_n, NA, NA, NA), + PINGROUP(120, cci_async, NA, NA, NA, NA, NA, NA), + PINGROUP(121, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(122, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(123, hdmi_dtest, NA, NA, NA, NA, NA, NA), + PINGROUP(124, spdif_tx, ldo_en, NA, NA, NA, NA, NA), + PINGROUP(125, ldo_update, hdmi_rcv, NA, NA, NA, NA, NA), + PINGROUP(126, gcc_vtt, NA, NA, NA, NA, NA, NA), + PINGROUP(127, gcc_obt, NA, NA, NA, NA, NA, NA), + PINGROUP(128, blsp_spi10_cs3, NA, NA, NA, NA, NA, NA), + PINGROUP(129, sata_act, NA, NA, NA, NA, NA, NA), + PINGROUP(130, uim, blsp_spi7, blsp_uart7, blsp_uim7, NA, NA, NA), + PINGROUP(131, uim, blsp_spi7, blsp_uart7, blsp_uim7, NA, NA, NA), + PINGROUP(132, uim, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA), + PINGROUP(133, uim, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA), + PINGROUP(134, hsic, NA, NA, NA, NA, NA, NA), + PINGROUP(135, hsic, NA, NA, NA, NA, NA, NA), + PINGROUP(136, spdif_tx, NA, NA, NA, NA, NA, NA), + PINGROUP(137, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(138, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(139, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(140, pci_e1_rst_n, pci_e1_rst, NA, NA, NA, NA, NA), + PINGROUP(141, pci_e1_clkreq_n, NA, NA, NA, NA, NA, NA), + PINGROUP(142, spdif_tx, NA, NA, NA, NA, NA, NA), + PINGROUP(143, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(144, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(145, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(146, sdc_emmc_mode, NA, NA, NA, NA, NA, NA), + + SDC_PINGROUP(sdc1_clk, 0x2044, 13, 6), + SDC_PINGROUP(sdc1_cmd, 0x2044, 11, 3), + SDC_PINGROUP(sdc1_data, 0x2044, 9, 0), + SDC_PINGROUP(sdc2_clk, 0x2048, 14, 6), + SDC_PINGROUP(sdc2_cmd, 0x2048, 11, 3), + SDC_PINGROUP(sdc2_data, 0x2048, 9, 0), +}; + +#define NUM_GPIO_PINGROUPS 147 + +static const struct msm_pinctrl_soc_data apq8084_pinctrl = { + .pins = apq8084_pins, + .npins = ARRAY_SIZE(apq8084_pins), + .functions = apq8084_functions, + .nfunctions = ARRAY_SIZE(apq8084_functions), + .groups = apq8084_groups, + .ngroups = ARRAY_SIZE(apq8084_groups), + .ngpios = NUM_GPIO_PINGROUPS, +}; + +static int apq8084_pinctrl_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &apq8084_pinctrl); +} + +static const struct of_device_id apq8084_pinctrl_of_match[] = { + { .compatible = "qcom,apq8084-pinctrl", }, + { }, +}; + +static struct platform_driver apq8084_pinctrl_driver = { + .driver = { + .name = "apq8084-pinctrl", + .owner = THIS_MODULE, + .of_match_table = apq8084_pinctrl_of_match, + }, + .probe = apq8084_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init apq8084_pinctrl_init(void) +{ + return platform_driver_register(&apq8084_pinctrl_driver); +} +arch_initcall(apq8084_pinctrl_init); + +static void __exit apq8084_pinctrl_exit(void) +{ + platform_driver_unregister(&apq8084_pinctrl_driver); +} +module_exit(apq8084_pinctrl_exit); + +MODULE_DESCRIPTION("Qualcomm APQ8084 pinctrl driver"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, apq8084_pinctrl_of_match); diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c index 767cf1120b20..81f49a9b4dbe 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c @@ -211,6 +211,7 @@ static const unsigned int sdc3_data_pins[] = { 71 }; .intr_status_bit = 0, \ .intr_ack_high = 1, \ .intr_target_bit = 0, \ + .intr_target_kpss_val = 4, \ .intr_raw_status_bit = 3, \ .intr_polarity_bit = 1, \ .intr_detection_bit = 2, \ @@ -236,6 +237,7 @@ static const unsigned int sdc3_data_pins[] = { 71 }; .intr_enable_bit = -1, \ .intr_status_bit = -1, \ .intr_target_bit = -1, \ + .intr_target_kpss_val = -1, \ .intr_raw_status_bit = -1, \ .intr_polarity_bit = -1, \ .intr_detection_bit = -1, \ diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 2738108caff2..d30dddd21323 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -12,6 +12,7 @@ * GNU General Public License for more details. */ +#include <linux/delay.h> #include <linux/err.h> #include <linux/io.h> #include <linux/module.h> @@ -26,6 +27,7 @@ #include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/spinlock.h> +#include <linux/reboot.h> #include "../core.h" #include "../pinconf.h" @@ -33,12 +35,14 @@ #include "../pinctrl-utils.h" #define MAX_NR_GPIO 300 +#define PS_HOLD_OFFSET 0x820 /** * struct msm_pinctrl - state for a pinctrl-msm device * @dev: device handle. * @pctrl: pinctrl handle. * @chip: gpiochip handle. + * @restart_nb: restart notifier block. * @irq: parent irq for the TLMM irq_chip. * @lock: Spinlock to protect register resources as well * as msm_pinctrl data structures. @@ -52,6 +56,7 @@ struct msm_pinctrl { struct device *dev; struct pinctrl_dev *pctrl; struct gpio_chip chip; + struct notifier_block restart_nb; int irq; spinlock_t lock; @@ -130,9 +135,9 @@ static int msm_get_function_groups(struct pinctrl_dev *pctldev, return 0; } -static int msm_pinmux_enable(struct pinctrl_dev *pctldev, - unsigned function, - unsigned group) +static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) { struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); const struct msm_pingroup *g; @@ -166,7 +171,7 @@ static const struct pinmux_ops msm_pinmux_ops = { .get_functions_count = msm_get_functions_count, .get_function_name = msm_get_function_name, .get_function_groups = msm_get_function_groups, - .enable = msm_pinmux_enable, + .set_mux = msm_pinmux_set_mux, }; static int msm_config_reg(struct msm_pinctrl *pctrl, @@ -649,8 +654,6 @@ static void msm_gpio_irq_ack(struct irq_data *d) spin_unlock_irqrestore(&pctrl->lock, flags); } -#define INTR_TARGET_PROC_APPS 4 - static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); @@ -674,7 +677,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) /* Route interrupts to application cpu */ val = readl(pctrl->regs + g->intr_target_reg); val &= ~(7 << g->intr_target_bit); - val |= INTR_TARGET_PROC_APPS << g->intr_target_bit; + val |= g->intr_target_kpss_val << g->intr_target_bit; writel(val, pctrl->regs + g->intr_target_reg); /* Update configuration for gpio. @@ -829,6 +832,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio); if (ret) { dev_err(pctrl->dev, "Failed to add pin range\n"); + gpiochip_remove(&pctrl->chip); return ret; } @@ -839,6 +843,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) IRQ_TYPE_NONE); if (ret) { dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n"); + gpiochip_remove(&pctrl->chip); return -ENOSYS; } @@ -848,6 +853,32 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) return 0; } +static int msm_ps_hold_restart(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct msm_pinctrl *pctrl = container_of(nb, struct msm_pinctrl, restart_nb); + + writel(0, pctrl->regs + PS_HOLD_OFFSET); + mdelay(1000); + return NOTIFY_DONE; +} + +static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl) +{ + int i = 0; + const struct msm_function *func = pctrl->soc->functions; + + for (; i <= pctrl->soc->nfunctions; i++) + if (!strcmp(func[i].name, "ps_hold")) { + pctrl->restart_nb.notifier_call = msm_ps_hold_restart; + pctrl->restart_nb.priority = 128; + if (register_restart_handler(&pctrl->restart_nb)) + dev_err(pctrl->dev, + "failed to setup restart handler.\n"); + break; + } +} + int msm_pinctrl_probe(struct platform_device *pdev, const struct msm_pinctrl_soc_data *soc_data) { @@ -871,6 +902,8 @@ int msm_pinctrl_probe(struct platform_device *pdev, if (IS_ERR(pctrl->regs)) return PTR_ERR(pctrl->regs); + msm_pinctrl_setup_pm_reset(pctrl); + pctrl->irq = platform_get_irq(pdev, 0); if (pctrl->irq < 0) { dev_err(&pdev->dev, "No interrupt defined for msmgpio\n"); @@ -913,6 +946,8 @@ int msm_pinctrl_remove(struct platform_device *pdev) pinctrl_unregister(pctrl->pctrl); + unregister_restart_handler(&pctrl->restart_nb); + return 0; } EXPORT_SYMBOL(msm_pinctrl_remove); diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h index 7b2a227a590a..b952c4b4a8e9 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.h +++ b/drivers/pinctrl/qcom/pinctrl-msm.h @@ -53,6 +53,8 @@ struct msm_function { * @intr_status_bit: Offset in @intr_status_reg for reading and acking the interrupt * status. * @intr_target_bit: Offset in @intr_target_reg for configuring the interrupt routing. + * @intr_target_kpss_val: Value in @intr_target_bit for specifying that the interrupt from + * this gpio should get routed to the KPSS processor. * @intr_raw_status_bit: Offset in @intr_cfg_reg for the raw status bit. * @intr_polarity_bit: Offset in @intr_cfg_reg for specifying polarity of the interrupt. * @intr_detection_bit: Offset in @intr_cfg_reg for specifying interrupt type. @@ -88,6 +90,7 @@ struct msm_pingroup { unsigned intr_ack_high:1; unsigned intr_target_bit:5; + unsigned intr_target_kpss_val:5; unsigned intr_raw_status_bit:5; unsigned intr_polarity_bit:5; unsigned intr_detection_bit:5; diff --git a/drivers/pinctrl/qcom/pinctrl-msm8960.c b/drivers/pinctrl/qcom/pinctrl-msm8960.c index 35047036a053..2ab21ce5575a 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8960.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8960.c @@ -384,6 +384,7 @@ static const unsigned int sdc3_data_pins[] = { 157 }; .intr_status_bit = 0, \ .intr_ack_high = 1, \ .intr_target_bit = 0, \ + .intr_target_kpss_val = 4, \ .intr_raw_status_bit = 3, \ .intr_polarity_bit = 1, \ .intr_detection_bit = 2, \ @@ -409,6 +410,7 @@ static const unsigned int sdc3_data_pins[] = { 157 }; .intr_enable_bit = -1, \ .intr_status_bit = -1, \ .intr_target_bit = -1, \ + .intr_target_kpss_val = -1, \ .intr_raw_status_bit = -1, \ .intr_polarity_bit = -1, \ .intr_detection_bit = -1, \ diff --git a/drivers/pinctrl/qcom/pinctrl-msm8x74.c b/drivers/pinctrl/qcom/pinctrl-msm8x74.c index 8c9720154d1e..3c858384d041 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8x74.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8x74.c @@ -366,6 +366,7 @@ static const unsigned int sdc2_data_pins[] = { 151 }; .intr_enable_bit = 0, \ .intr_status_bit = 0, \ .intr_target_bit = 5, \ + .intr_target_kpss_val = 4, \ .intr_raw_status_bit = 4, \ .intr_polarity_bit = 1, \ .intr_detection_bit = 2, \ @@ -391,6 +392,7 @@ static const unsigned int sdc2_data_pins[] = { 151 }; .intr_enable_bit = -1, \ .intr_status_bit = -1, \ .intr_target_bit = -1, \ + .intr_target_kpss_val = -1, \ .intr_raw_status_bit = -1, \ .intr_polarity_bit = -1, \ .intr_detection_bit = -1, \ diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c index 603da2f9dd95..b995ec2c5d16 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c @@ -364,8 +364,9 @@ static void exynos5440_pinmux_setup(struct pinctrl_dev *pctldev, unsigned select } /* enable a specified pinmux by writing to registers */ -static int exynos5440_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group) +static int exynos5440_pinmux_set_mux(struct pinctrl_dev *pctldev, + unsigned selector, + unsigned group) { exynos5440_pinmux_setup(pctldev, selector, group, true); return 0; @@ -387,7 +388,7 @@ static const struct pinmux_ops exynos5440_pinmux_ops = { .get_functions_count = exynos5440_get_functions_count, .get_function_name = exynos5440_pinmux_get_fname, .get_function_groups = exynos5440_pinmux_get_groups, - .enable = exynos5440_pinmux_enable, + .set_mux = exynos5440_pinmux_set_mux, .gpio_set_direction = exynos5440_pinmux_gpio_set_direction, }; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index b07406da333c..4a47691c32b1 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -401,8 +401,9 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector, } /* enable a specified pinmux by writing to registers */ -static int samsung_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group) +static int samsung_pinmux_set_mux(struct pinctrl_dev *pctldev, + unsigned selector, + unsigned group) { samsung_pinmux_setup(pctldev, selector, group, true); return 0; @@ -413,7 +414,7 @@ static const struct pinmux_ops samsung_pinmux_ops = { .get_functions_count = samsung_get_functions_count, .get_function_name = samsung_pinmux_get_fname, .get_function_groups = samsung_pinmux_get_groups, - .enable = samsung_pinmux_enable, + .set_mux = samsung_pinmux_set_mux, }; /* set or get the pin config settings for a specified pin */ diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index b9b464d0578c..6572c233f73d 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -542,7 +542,7 @@ static int sh_pfc_probe(struct platform_device *pdev) */ ret = sh_pfc_register_pinctrl(pfc); if (unlikely(ret != 0)) - goto error; + return ret; #ifdef CONFIG_GPIO_SH_PFC /* @@ -564,11 +564,6 @@ static int sh_pfc_probe(struct platform_device *pdev) dev_info(pfc->dev, "%s support registered\n", info->name); return 0; - -error: - if (info->ops && info->ops->exit) - info->ops->exit(pfc); - return ret; } static int sh_pfc_remove(struct platform_device *pdev) @@ -580,9 +575,6 @@ static int sh_pfc_remove(struct platform_device *pdev) #endif sh_pfc_unregister_pinctrl(pfc); - if (pfc->info->ops && pfc->info->ops->exit) - pfc->info->ops->exit(pfc); - return 0; } diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h index b7b0e6ccf305..3daaa5241c47 100644 --- a/drivers/pinctrl/sh-pfc/core.h +++ b/drivers/pinctrl/sh-pfc/core.h @@ -33,7 +33,6 @@ struct sh_pfc_pin_range { struct sh_pfc { struct device *dev; const struct sh_pfc_soc_info *info; - void *soc_data; spinlock_t lock; unsigned int num_windows; diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c index ce9fb7aa8ba3..280a56f97786 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c @@ -2717,14 +2717,14 @@ static void r8a73a4_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, iowrite8(value, addr); } -static const struct sh_pfc_soc_operations r8a73a4_pinmux_ops = { +static const struct sh_pfc_soc_operations r8a73a4_pfc_ops = { .get_bias = r8a73a4_pinmux_get_bias, .set_bias = r8a73a4_pinmux_set_bias, }; const struct sh_pfc_soc_info r8a73a4_pinmux_info = { .name = "r8a73a4_pfc", - .ops = &r8a73a4_pinmux_ops, + .ops = &r8a73a4_pfc_ops, .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END }, .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END }, diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c index e4c1ef477053..b486e9d20cc2 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c @@ -3752,14 +3752,14 @@ static void r8a7740_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, iowrite8(value, addr); } -static const struct sh_pfc_soc_operations r8a7740_pinmux_ops = { +static const struct sh_pfc_soc_operations r8a7740_pfc_ops = { .get_bias = r8a7740_pinmux_get_bias, .set_bias = r8a7740_pinmux_set_bias, }; const struct sh_pfc_soc_info r8a7740_pinmux_info = { .name = "r8a7740_pfc", - .ops = &r8a7740_pinmux_ops, + .ops = &r8a7740_pfc_ops, .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END }, diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7372.c b/drivers/pinctrl/sh-pfc/pfc-sh7372.c index d9158b3b2919..8211f66a2f68 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh7372.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh7372.c @@ -2614,14 +2614,14 @@ static void sh7372_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, iowrite8(value, addr); } -static const struct sh_pfc_soc_operations sh7372_pinmux_ops = { +static const struct sh_pfc_soc_operations sh7372_pfc_ops = { .get_bias = sh7372_pinmux_get_bias, .set_bias = sh7372_pinmux_set_bias, }; const struct sh_pfc_soc_info sh7372_pinmux_info = { .name = "sh7372_pfc", - .ops = &sh7372_pinmux_ops, + .ops = &sh7372_pfc_ops, .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END }, .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END }, diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c index 0bd8f4401b42..d2efbfb776ac 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c @@ -3824,39 +3824,28 @@ static void sh73a0_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, * SoC information */ -struct sh73a0_pinmux_data { - struct regulator_dev *vccq_mc0; -}; - static int sh73a0_pinmux_soc_init(struct sh_pfc *pfc) { - struct sh73a0_pinmux_data *data; struct regulator_config cfg = { }; + struct regulator_dev *vccq; int ret; - data = devm_kzalloc(pfc->dev, sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - cfg.dev = pfc->dev; cfg.init_data = &sh73a0_vccq_mc0_init_data; cfg.driver_data = pfc; - data->vccq_mc0 = devm_regulator_register(pfc->dev, - &sh73a0_vccq_mc0_desc, &cfg); - if (IS_ERR(data->vccq_mc0)) { - ret = PTR_ERR(data->vccq_mc0); + vccq = devm_regulator_register(pfc->dev, &sh73a0_vccq_mc0_desc, &cfg); + if (IS_ERR(vccq)) { + ret = PTR_ERR(vccq); dev_err(pfc->dev, "Failed to register VCCQ MC0 regulator: %d\n", ret); return ret; } - pfc->soc_data = data; - return 0; } -static const struct sh_pfc_soc_operations sh73a0_pinmux_ops = { +static const struct sh_pfc_soc_operations sh73a0_pfc_ops = { .init = sh73a0_pinmux_soc_init, .get_bias = sh73a0_pinmux_get_bias, .set_bias = sh73a0_pinmux_set_bias, @@ -3864,7 +3853,7 @@ static const struct sh_pfc_soc_operations sh73a0_pinmux_ops = { const struct sh_pfc_soc_info sh73a0_pinmux_info = { .name = "sh73a0_pfc", - .ops = &sh73a0_pinmux_ops, + .ops = &sh73a0_pfc_ops, .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END }, .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END }, diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c index 11db3ee39d40..910deaefa0ac 100644 --- a/drivers/pinctrl/sh-pfc/pinctrl.c +++ b/drivers/pinctrl/sh-pfc/pinctrl.c @@ -312,8 +312,8 @@ static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev, return 0; } -static int sh_pfc_func_enable(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group) +static int sh_pfc_func_set_mux(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) { struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); struct sh_pfc *pfc = pmx->pfc; @@ -442,7 +442,7 @@ static const struct pinmux_ops sh_pfc_pinmux_ops = { .get_functions_count = sh_pfc_get_functions_count, .get_function_name = sh_pfc_get_function_name, .get_function_groups = sh_pfc_get_function_groups, - .enable = sh_pfc_func_enable, + .set_mux = sh_pfc_func_set_mux, .gpio_request_enable = sh_pfc_gpio_request_enable, .gpio_disable_free = sh_pfc_gpio_disable_free, .gpio_set_direction = sh_pfc_gpio_set_direction, diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index d482c40b012a..5b7283182c1e 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -116,7 +116,6 @@ struct sh_pfc; struct sh_pfc_soc_operations { int (*init)(struct sh_pfc *pfc); - void (*exit)(struct sh_pfc *pfc); unsigned int (*get_bias)(struct sh_pfc *pfc, unsigned int pin); void (*set_bias)(struct sh_pfc *pfc, unsigned int pin, unsigned int bias); diff --git a/drivers/pinctrl/sirf/pinctrl-atlas6.c b/drivers/pinctrl/sirf/pinctrl-atlas6.c index c4dd3d5cf9c3..45f8391ddb34 100644 --- a/drivers/pinctrl/sirf/pinctrl-atlas6.c +++ b/drivers/pinctrl/sirf/pinctrl-atlas6.c @@ -134,8 +134,9 @@ static const struct sirfsoc_muxmask lcd_16bits_sirfsoc_muxmask[] = { .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) | + .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), }, }; @@ -148,14 +149,15 @@ static const struct sirfsoc_padmux lcd_16bits_padmux = { .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 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) | + .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, @@ -174,21 +176,23 @@ static const struct sirfsoc_padmux lcd_18bits_padmux = { .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 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) | + .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), + .mask = BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | + BIT(21) | BIT(22) | BIT(23), }, }; @@ -200,14 +204,16 @@ static const struct sirfsoc_padmux lcd_24bits_padmux = { .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 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) | + .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, @@ -226,8 +232,8 @@ static const struct sirfsoc_padmux lcdrom_padmux = { .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 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[] = { { @@ -371,11 +377,42 @@ static const struct sirfsoc_padmux cko1_padmux = { static const unsigned cko1_pins[] = { 42 }; -static const struct sirfsoc_muxmask i2s_muxmask[] = { +static const struct sirfsoc_muxmask i2s_mclk_muxmask[] = { { .group = 1, .mask = BIT(10), - }, { + }, +}; + +static const struct sirfsoc_padmux i2s_mclk_padmux = { + .muxmask_counts = ARRAY_SIZE(i2s_mclk_muxmask), + .muxmask = i2s_mclk_muxmask, + .ctrlreg = SIRFSOC_RSC_PIN_MUX, + .funcmask = BIT(3), + .funcval = BIT(3), +}; + +static const unsigned i2s_mclk_pins[] = { 42 }; + +static const struct sirfsoc_muxmask i2s_ext_clk_input_muxmask[] = { + { + .group = 1, + .mask = BIT(19), + }, +}; + +static const struct sirfsoc_padmux i2s_ext_clk_input_padmux = { + .muxmask_counts = ARRAY_SIZE(i2s_ext_clk_input_muxmask), + .muxmask = i2s_ext_clk_input_muxmask, + .ctrlreg = SIRFSOC_RSC_PIN_MUX, + .funcmask = BIT(2), + .funcval = BIT(2), +}; + +static const unsigned i2s_ext_clk_input_pins[] = { 51 }; + +static const struct sirfsoc_muxmask i2s_muxmask[] = { + { .group = 3, .mask = BIT(2) | BIT(3) | BIT(4) | BIT(5), }, @@ -385,17 +422,12 @@ static const struct sirfsoc_padmux i2s_padmux = { .muxmask_counts = ARRAY_SIZE(i2s_muxmask), .muxmask = i2s_muxmask, .ctrlreg = SIRFSOC_RSC_PIN_MUX, - .funcmask = BIT(3), - .funcval = BIT(3), }; -static const unsigned i2s_pins[] = { 42, 98, 99, 100, 101 }; +static const unsigned i2s_pins[] = { 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), }, @@ -405,17 +437,12 @@ static const struct sirfsoc_padmux i2s_no_din_padmux = { .muxmask_counts = ARRAY_SIZE(i2s_no_din_muxmask), .muxmask = i2s_no_din_muxmask, .ctrlreg = SIRFSOC_RSC_PIN_MUX, - .funcmask = BIT(3), - .funcval = BIT(3), }; -static const unsigned i2s_no_din_pins[] = { 42, 98, 99, 100 }; +static const unsigned i2s_no_din_pins[] = { 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), }, @@ -425,11 +452,11 @@ static const struct sirfsoc_padmux i2s_6chn_padmux = { .muxmask_counts = ARRAY_SIZE(i2s_6chn_muxmask), .muxmask = i2s_6chn_muxmask, .ctrlreg = SIRFSOC_RSC_PIN_MUX, - .funcmask = BIT(1) | BIT(3) | BIT(9), - .funcval = BIT(1) | BIT(3) | BIT(9), + .funcmask = BIT(1) | BIT(9), + .funcval = BIT(1) | BIT(9), }; -static const unsigned i2s_6chn_pins[] = { 42, 52, 55, 98, 99, 100, 101 }; +static const unsigned i2s_6chn_pins[] = { 52, 55, 98, 99, 100, 101 }; static const struct sirfsoc_muxmask ac97_muxmask[] = { { @@ -716,7 +743,8 @@ static const struct sirfsoc_padmux vip_padmux = { .funcval = BIT(18), }; -static const unsigned vip_pins[] = { 36, 37, 38, 40, 41, 56, 57, 58, 59, 60, 61 }; +static const unsigned vip_pins[] = { 36, 37, 38, 40, 41, 56, 57, 58, 59, + 60, 61 }; static const struct sirfsoc_muxmask vip_noupli_muxmask[] = { { @@ -737,7 +765,8 @@ static const struct sirfsoc_padmux vip_noupli_padmux = { .funcval = BIT(15), }; -static const unsigned vip_noupli_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, 87, 88, 89 }; +static const unsigned vip_noupli_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, + 87, 88, 89 }; static const struct sirfsoc_muxmask i2c0_muxmask[] = { { @@ -876,7 +905,8 @@ static const struct sirfsoc_padmux usb0_upli_drvbus_padmux = { .funcval = 0, }; -static const unsigned usb0_upli_drvbus_pins[] = { 36, 37, 38, 39, 40, 41, 56, 57, 58, 59, 60, 61 }; +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[] = { { @@ -968,6 +998,8 @@ static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = { SIRFSOC_PIN_GROUP("usb1_dp_dngrp", usb1_dp_dn_pins), SIRFSOC_PIN_GROUP("uart1_route_io_usb1grp", uart1_route_io_usb1_pins), SIRFSOC_PIN_GROUP("pulse_countgrp", pulse_count_pins), + SIRFSOC_PIN_GROUP("i2smclkgrp", i2s_mclk_pins), + SIRFSOC_PIN_GROUP("i2s_ext_clk_inputgrp", i2s_ext_clk_input_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), @@ -1017,8 +1049,11 @@ 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 usb1_dp_dngrp[] = { "usb1_dp_dngrp" }; -static const char * const uart1_route_io_usb1grp[] = { "uart1_route_io_usb1grp" }; +static const char * const + uart1_route_io_usb1grp[] = { "uart1_route_io_usb1grp" }; static const char * const pulse_countgrp[] = { "pulse_countgrp" }; +static const char * const i2smclkgrp[] = { "i2smclkgrp" }; +static const char * const i2s_ext_clk_inputgrp[] = { "i2s_ext_clk_inputgrp" }; static const char * const i2sgrp[] = { "i2sgrp" }; static const char * const i2s_no_dingrp[] = { "i2s_no_dingrp" }; static const char * const i2s_6chngrp[] = { "i2s_6chngrp" }; @@ -1038,7 +1073,8 @@ static const struct sirfsoc_pmx_func sirfsoc_pmx_functions[] = { uart0_nostreamctrl_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("uart2_nostreamctrl", + uart2_nostreamctrlgrp, uart2_nostreamctrl_padmux), SIRFSOC_PMX_FUNCTION("usp0", usp0grp, usp0_padmux), SIRFSOC_PMX_FUNCTION("usp0_uart_nostreamctrl", usp0_uart_nostreamctrl_grp, @@ -1068,12 +1104,19 @@ static const struct sirfsoc_pmx_func sirfsoc_pmx_functions[] = { 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("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("usb1_dp_dn", usb1_dp_dngrp, usb1_dp_dn_padmux), - SIRFSOC_PMX_FUNCTION("uart1_route_io_usb1", uart1_route_io_usb1grp, uart1_route_io_usb1_padmux), + SIRFSOC_PMX_FUNCTION("uart1_route_io_usb1", + uart1_route_io_usb1grp, uart1_route_io_usb1_padmux), SIRFSOC_PMX_FUNCTION("pulse_count", pulse_countgrp, pulse_count_padmux), + SIRFSOC_PMX_FUNCTION("i2s_mclk", i2smclkgrp, i2s_mclk_padmux), + SIRFSOC_PMX_FUNCTION("i2s_ext_clk_input", i2s_ext_clk_inputgrp, + i2s_ext_clk_input_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), diff --git a/drivers/pinctrl/sirf/pinctrl-prima2.c b/drivers/pinctrl/sirf/pinctrl-prima2.c index 8aa76f0776d7..357678ee28e3 100644 --- a/drivers/pinctrl/sirf/pinctrl-prima2.c +++ b/drivers/pinctrl/sirf/pinctrl-prima2.c @@ -135,8 +135,9 @@ static const struct pinctrl_pin_desc sirfsoc_pads[] = { static const struct sirfsoc_muxmask lcd_16bits_sirfsoc_muxmask[] = { { .group = 3, - .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | - BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | + .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | + BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | + BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18), }, { .group = 2, @@ -152,14 +153,15 @@ static const struct sirfsoc_padmux lcd_16bits_padmux = { .funcval = 0, }; -static const unsigned lcd_16bits_pins[] = { 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114 }; +static const unsigned lcd_16bits_pins[] = { 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114 }; static const struct sirfsoc_muxmask lcd_18bits_muxmask[] = { { .group = 3, - .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | - BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | + .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | + BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | + BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18), }, { .group = 2, @@ -178,21 +180,23 @@ static const struct sirfsoc_padmux lcd_18bits_padmux = { .funcval = 0, }; -static const unsigned lcd_18bits_pins[] = { 16, 17, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114}; +static const unsigned lcd_18bits_pins[] = { 16, 17, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114}; static const struct sirfsoc_muxmask lcd_24bits_muxmask[] = { { .group = 3, - .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | - BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | + .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | + BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | + BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18), }, { .group = 2, .mask = BIT(31), }, { .group = 0, - .mask = BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23), + .mask = BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | + BIT(21) | BIT(22) | BIT(23), }, }; @@ -204,14 +208,16 @@ static const struct sirfsoc_padmux lcd_24bits_padmux = { .funcval = 0, }; -static const unsigned lcd_24bits_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114 }; +static const unsigned lcd_24bits_pins[] = { 16, 17, 18, 19, 20, 21, 22, 23, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114 }; static const struct sirfsoc_muxmask lcdrom_muxmask[] = { { .group = 3, - .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | - BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | + .mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | + BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | + BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18), }, { .group = 2, @@ -230,8 +236,8 @@ static const struct sirfsoc_padmux lcdrom_padmux = { .funcval = BIT(4), }; -static const unsigned lcdrom_pins[] = { 23, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114 }; +static const unsigned lcdrom_pins[] = { 23, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114 }; static const struct sirfsoc_muxmask uart0_muxmask[] = { { @@ -380,12 +386,44 @@ static const struct sirfsoc_padmux cko1_padmux = { static const unsigned cko1_pins[] = { 42 }; +static const struct sirfsoc_muxmask i2s_mclk_muxmask[] = { + { + .group = 1, + .mask = BIT(10), + }, +}; + +static const struct sirfsoc_padmux i2s_mclk_padmux = { + .muxmask_counts = ARRAY_SIZE(i2s_mclk_muxmask), + .muxmask = i2s_mclk_muxmask, + .ctrlreg = SIRFSOC_RSC_PIN_MUX, + .funcmask = BIT(3), + .funcval = BIT(3), +}; + +static const unsigned i2s_mclk_pins[] = { 42 }; + +static const struct sirfsoc_muxmask i2s_ext_clk_input_muxmask[] = { + { + .group = 1, + .mask = BIT(19), + }, +}; + +static const struct sirfsoc_padmux i2s_ext_clk_input_padmux = { + .muxmask_counts = ARRAY_SIZE(i2s_ext_clk_input_muxmask), + .muxmask = i2s_ext_clk_input_muxmask, + .ctrlreg = SIRFSOC_RSC_PIN_MUX, + .funcmask = BIT(2), + .funcval = BIT(2), +}; + +static const unsigned i2s_ext_clk_input_pins[] = { 51 }; + static const struct sirfsoc_muxmask i2s_muxmask[] = { { .group = 1, - .mask = - BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(19) - | BIT(23) | BIT(28), + .mask = BIT(11) | BIT(12) | BIT(13) | BIT(14), }, }; @@ -393,11 +431,42 @@ static const struct sirfsoc_padmux i2s_padmux = { .muxmask_counts = ARRAY_SIZE(i2s_muxmask), .muxmask = i2s_muxmask, .ctrlreg = SIRFSOC_RSC_PIN_MUX, - .funcmask = BIT(3) | BIT(9), - .funcval = BIT(3), }; -static const unsigned i2s_pins[] = { 42, 43, 44, 45, 46, 51, 55, 60 }; +static const unsigned i2s_pins[] = { 43, 44, 45, 46 }; + +static const struct sirfsoc_muxmask i2s_no_din_muxmask[] = { + { + .group = 1, + .mask = BIT(11) | BIT(12) | BIT(14), + }, +}; + +static const struct sirfsoc_padmux i2s_no_din_padmux = { + .muxmask_counts = ARRAY_SIZE(i2s_no_din_muxmask), + .muxmask = i2s_no_din_muxmask, + .ctrlreg = SIRFSOC_RSC_PIN_MUX, +}; + +static const unsigned i2s_no_din_pins[] = { 43, 44, 46 }; + +static const struct sirfsoc_muxmask i2s_6chn_muxmask[] = { + { + .group = 1, + .mask = BIT(11) | BIT(12) | BIT(13) | BIT(14) + | BIT(23) | BIT(28), + }, +}; + +static const struct sirfsoc_padmux i2s_6chn_padmux = { + .muxmask_counts = ARRAY_SIZE(i2s_6chn_muxmask), + .muxmask = i2s_6chn_muxmask, + .ctrlreg = SIRFSOC_RSC_PIN_MUX, + .funcmask = BIT(1) | BIT(9), + .funcval = BIT(1) | BIT(9), +}; + +static const unsigned i2s_6chn_pins[] = { 43, 44, 45, 46, 55, 60 }; static const struct sirfsoc_muxmask ac97_muxmask[] = { { @@ -685,7 +754,8 @@ static const struct sirfsoc_padmux vip_padmux = { .funcval = 0, }; -static const unsigned vip_pins[] = { 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 }; +static const unsigned vip_pins[] = { 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89 }; static const struct sirfsoc_muxmask i2c0_muxmask[] = { { @@ -735,7 +805,8 @@ static const struct sirfsoc_padmux viprom_padmux = { .funcval = BIT(0), }; -static const unsigned viprom_pins[] = { 12, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 }; +static const unsigned viprom_pins[] = { 12, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89 }; static const struct sirfsoc_muxmask pwm0_muxmask[] = { { @@ -918,7 +989,11 @@ static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = { SIRFSOC_PIN_GROUP("usb1_dp_dngrp", usb1_dp_dn_pins), SIRFSOC_PIN_GROUP("uart1_route_io_usb1grp", uart1_route_io_usb1_pins), SIRFSOC_PIN_GROUP("pulse_countgrp", pulse_count_pins), + SIRFSOC_PIN_GROUP("i2smclkgrp", i2s_mclk_pins), + SIRFSOC_PIN_GROUP("i2s_ext_clk_inputgrp", i2s_ext_clk_input_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), @@ -936,16 +1011,19 @@ 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 usp0_uart_nostreamctrl_grp[] = - { "usp0_uart_nostreamctrl_grp" }; +static const char * const usp0_uart_nostreamctrl_grp[] = { + "usp0_uart_nostreamctrl_grp" +}; static const char * const usp0_only_utfs_grp[] = { "usp0_only_utfs_grp" }; static const char * const usp0_only_urfs_grp[] = { "usp0_only_urfs_grp" }; static const char * const usp1grp[] = { "usp1grp" }; -static const char * const usp1_uart_nostreamctrl_grp[] = - { "usp1_uart_nostreamctrl_grp" }; +static const char * const usp1_uart_nostreamctrl_grp[] = { + "usp1_uart_nostreamctrl_grp" +}; static const char * const usp2grp[] = { "usp2grp" }; -static const char * const usp2_uart_nostreamctrl_grp[] = - { "usp2_uart_nostreamctrl_grp" }; +static const char * const usp2_uart_nostreamctrl_grp[] = { + "usp2_uart_nostreamctrl_grp" +}; static const char * const i2c0grp[] = { "i2c0grp" }; static const char * const i2c1grp[] = { "i2c1grp" }; static const char * const pwm0grp[] = { "pwm0grp" }; @@ -966,9 +1044,14 @@ static const char * const sdmmc5grp[] = { "sdmmc5grp" }; static const char * const usb0_utmi_drvbusgrp[] = { "usb0_utmi_drvbusgrp" }; static const char * const usb1_utmi_drvbusgrp[] = { "usb1_utmi_drvbusgrp" }; static const char * const usb1_dp_dngrp[] = { "usb1_dp_dngrp" }; -static const char * const uart1_route_io_usb1grp[] = { "uart1_route_io_usb1grp" }; +static const char * const + uart1_route_io_usb1grp[] = { "uart1_route_io_usb1grp" }; static const char * const pulse_countgrp[] = { "pulse_countgrp" }; +static const char * const i2smclkgrp[] = { "i2smclkgrp" }; +static const char * const i2s_ext_clk_inputgrp[] = { "i2s_ext_clk_inputgrp" }; 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" }; @@ -981,15 +1064,19 @@ static const struct sirfsoc_pmx_func sirfsoc_pmx_functions[] = { 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("uart0_nostreamctrl", uart0_nostreamctrlgrp, uart0_nostreamctrl_padmux), + SIRFSOC_PMX_FUNCTION("uart0_nostreamctrl", + uart0_nostreamctrlgrp, uart0_nostreamctrl_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("uart2_nostreamctrl", + uart2_nostreamctrlgrp, uart2_nostreamctrl_padmux), SIRFSOC_PMX_FUNCTION("usp0", usp0grp, usp0_padmux), SIRFSOC_PMX_FUNCTION("usp0_uart_nostreamctrl", usp0_uart_nostreamctrl_grp, usp0_uart_nostreamctrl_padmux), - SIRFSOC_PMX_FUNCTION("usp0_only_utfs", usp0_only_utfs_grp, usp0_only_utfs_padmux), - SIRFSOC_PMX_FUNCTION("usp0_only_urfs", usp0_only_urfs_grp, usp0_only_urfs_padmux), + SIRFSOC_PMX_FUNCTION("usp0_only_utfs", + usp0_only_utfs_grp, usp0_only_utfs_padmux), + SIRFSOC_PMX_FUNCTION("usp0_only_urfs", + usp0_only_urfs_grp, usp0_only_urfs_padmux), SIRFSOC_PMX_FUNCTION("usp1", usp1grp, usp1_padmux), SIRFSOC_PMX_FUNCTION("usp1_uart_nostreamctrl", usp1_uart_nostreamctrl_grp, usp1_uart_nostreamctrl_padmux), @@ -1013,12 +1100,20 @@ static const struct sirfsoc_pmx_func sirfsoc_pmx_functions[] = { SIRFSOC_PMX_FUNCTION("sdmmc3", sdmmc3grp, sdmmc3_padmux), SIRFSOC_PMX_FUNCTION("sdmmc4", sdmmc4grp, sdmmc4_padmux), SIRFSOC_PMX_FUNCTION("sdmmc5", sdmmc5grp, sdmmc5_padmux), - SIRFSOC_PMX_FUNCTION("usb0_utmi_drvbus", usb0_utmi_drvbusgrp, usb0_utmi_drvbus_padmux), - SIRFSOC_PMX_FUNCTION("usb1_utmi_drvbus", usb1_utmi_drvbusgrp, usb1_utmi_drvbus_padmux), + SIRFSOC_PMX_FUNCTION("usb0_utmi_drvbus", + usb0_utmi_drvbusgrp, usb0_utmi_drvbus_padmux), + SIRFSOC_PMX_FUNCTION("usb1_utmi_drvbus", + usb1_utmi_drvbusgrp, usb1_utmi_drvbus_padmux), SIRFSOC_PMX_FUNCTION("usb1_dp_dn", usb1_dp_dngrp, usb1_dp_dn_padmux), - SIRFSOC_PMX_FUNCTION("uart1_route_io_usb1", uart1_route_io_usb1grp, uart1_route_io_usb1_padmux), + SIRFSOC_PMX_FUNCTION("uart1_route_io_usb1", + uart1_route_io_usb1grp, uart1_route_io_usb1_padmux), SIRFSOC_PMX_FUNCTION("pulse_count", pulse_countgrp, pulse_count_padmux), + SIRFSOC_PMX_FUNCTION("i2s_mclk", i2smclkgrp, i2s_mclk_padmux), + SIRFSOC_PMX_FUNCTION("i2s_ext_clk_input", i2s_ext_clk_inputgrp, + i2s_ext_clk_input_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), diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c index 4c1d7c68666d..b713bd59ffbb 100644 --- a/drivers/pinctrl/sirf/pinctrl-sirf.c +++ b/drivers/pinctrl/sirf/pinctrl-sirf.c @@ -58,17 +58,18 @@ static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev, return sirfsoc_pin_groups[selector].name; } -static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, - const unsigned **pins, - unsigned *num_pins) +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) +static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned offset) { seq_printf(s, " " DRIVER_NAME); } @@ -138,22 +139,25 @@ static struct pinctrl_ops sirfsoc_pctrl_ops = { 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) +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_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)); + 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)); + writel(muxval, spmx->gpio_virtbase + + SIRFSOC_GPIO_PAD_EN(mask[i].group)); } else { if (enable) writel(mask[i].mask, spmx->gpio_virtbase + @@ -175,8 +179,9 @@ static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector } } -static int sirfsoc_pinmux_enable(struct pinctrl_dev *pmxdev, unsigned selector, - unsigned group) +static int sirfsoc_pinmux_set_mux(struct pinctrl_dev *pmxdev, + unsigned selector, + unsigned group) { struct sirfsoc_pmx *spmx; @@ -197,9 +202,10 @@ static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev, 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) +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; @@ -218,9 +224,11 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev, spmx = pinctrl_dev_get_drvdata(pmxdev); if (!spmx->is_marco) { - muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group)); + 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)); + 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)); @@ -230,7 +238,7 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev, } static struct pinmux_ops sirfsoc_pinmux_ops = { - .enable = sirfsoc_pinmux_enable, + .set_mux = sirfsoc_pinmux_set_mux, .get_functions_count = sirfsoc_pinmux_get_funcs_count, .get_function_name = sirfsoc_pinmux_get_func_name, .get_function_groups = sirfsoc_pinmux_get_groups, @@ -518,24 +526,29 @@ static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned 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_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; + 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; + 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_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); + val &= ~(SIRFSOC_GPIO_CTL_INTR_LOW_MASK | + SIRFSOC_GPIO_CTL_INTR_TYPE_MASK); break; } @@ -694,7 +707,8 @@ static inline void sirfsoc_gpio_set_output(struct sirfsoc_gpio_chip *sgpio, spin_unlock_irqrestore(&bank->lock, flags); } -static int sirfsoc_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value) +static int sirfsoc_gpio_direction_output(struct gpio_chip *chip, + unsigned gpio, int value) { struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(chip); struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(sgpio, gpio); @@ -839,7 +853,7 @@ static int sirfsoc_gpio_probe(struct device_node *np) if (err) { dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n"); - goto out; + goto out_banks; } for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { @@ -898,8 +912,8 @@ static int __init sirfsoc_gpio_init(void) } subsys_initcall(sirfsoc_gpio_init); -MODULE_AUTHOR("Rongjun Ying <rongjun.ying@csr.com>, " - "Yuping Luo <yuping.luo@csr.com>, " - "Barry Song <baohua.song@csr.com>"); +MODULE_AUTHOR("Rongjun Ying <rongjun.ying@csr.com>"); +MODULE_AUTHOR("Yuping Luo <yuping.luo@csr.com>"); +MODULE_AUTHOR("Barry Song <baohua.song@csr.com>"); MODULE_DESCRIPTION("SIRFSOC pin control driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c index f72cc4e192bd..abdb05ac43dc 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.c +++ b/drivers/pinctrl/spear/pinctrl-spear.c @@ -268,7 +268,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev, return 0; } -static int spear_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function, +static int spear_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned function, unsigned group) { return spear_pinctrl_endisable(pctldev, function, group, true); @@ -338,7 +338,7 @@ static const struct pinmux_ops spear_pinmux_ops = { .get_functions_count = spear_pinctrl_get_funcs_count, .get_function_name = spear_pinctrl_get_func_name, .get_function_groups = spear_pinctrl_get_func_groups, - .enable = spear_pinctrl_enable, + .set_mux = spear_pinctrl_set_mux, .gpio_request_enable = gpio_request_enable, .gpio_disable_free = gpio_disable_free, }; diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c index 1a8bbfec60ca..6d57d43ab640 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1310.c +++ b/drivers/pinctrl/spear/pinctrl-spear1310.c @@ -2692,7 +2692,7 @@ static struct spear_pinctrl_machdata spear1310_machdata = { .modes_supported = false, }; -static struct of_device_id spear1310_pinctrl_of_match[] = { +static const struct of_device_id spear1310_pinctrl_of_match[] = { { .compatible = "st,spear1310-pinmux", }, diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c index 873966e2b99f..d243e43e7f6d 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1340.c +++ b/drivers/pinctrl/spear/pinctrl-spear1340.c @@ -2008,7 +2008,7 @@ static struct spear_pinctrl_machdata spear1340_machdata = { .modes_supported = false, }; -static struct of_device_id spear1340_pinctrl_of_match[] = { +static const struct of_device_id spear1340_pinctrl_of_match[] = { { .compatible = "st,spear1340-pinmux", }, diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c index 4777c0d0e730..9db83e9ee18c 100644 --- a/drivers/pinctrl/spear/pinctrl-spear300.c +++ b/drivers/pinctrl/spear/pinctrl-spear300.c @@ -646,7 +646,7 @@ static struct spear_function *spear300_functions[] = { &gpio1_function, }; -static struct of_device_id spear300_pinctrl_of_match[] = { +static const struct of_device_id spear300_pinctrl_of_match[] = { { .compatible = "st,spear300-pinmux", }, diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c index ed1d3608f486..db775a414b7a 100644 --- a/drivers/pinctrl/spear/pinctrl-spear310.c +++ b/drivers/pinctrl/spear/pinctrl-spear310.c @@ -371,7 +371,7 @@ static struct spear_function *spear310_functions[] = { &tdm_function, }; -static struct of_device_id spear310_pinctrl_of_match[] = { +static const struct of_device_id spear310_pinctrl_of_match[] = { { .compatible = "st,spear310-pinmux", }, diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c index b8e290a8c8c9..80fbd68e17bc 100644 --- a/drivers/pinctrl/spear/pinctrl-spear320.c +++ b/drivers/pinctrl/spear/pinctrl-spear320.c @@ -3410,7 +3410,7 @@ static struct spear_function *spear320_functions[] = { &i2c2_function, }; -static struct of_device_id spear320_pinctrl_of_match[] = { +static const struct of_device_id spear320_pinctrl_of_match[] = { { .compatible = "st,spear320-pinmux", }, diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 3df66e366c87..ef9d804e55de 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -393,9 +393,9 @@ static void sunxi_pmx_set(struct pinctrl_dev *pctldev, spin_unlock_irqrestore(&pctl->lock, flags); } -static int sunxi_pmx_enable(struct pinctrl_dev *pctldev, - unsigned function, - unsigned group) +static int sunxi_pmx_set_mux(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) { struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); struct sunxi_pinctrl_group *g = pctl->groups + group; @@ -441,7 +441,7 @@ static const struct pinmux_ops sunxi_pmx_ops = { .get_functions_count = sunxi_pmx_get_funcs_cnt, .get_function_name = sunxi_pmx_get_func_name, .get_function_groups = sunxi_pmx_get_func_groups, - .enable = sunxi_pmx_enable, + .set_mux = sunxi_pmx_set_mux, .gpio_set_direction = sunxi_pmx_gpio_set_direction, }; diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c index 8cea355f9a81..d055d63309e4 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wmt.c +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c @@ -131,9 +131,9 @@ static int wmt_set_pinmux(struct wmt_pinctrl_data *data, unsigned func, return 0; } -static int wmt_pmx_enable(struct pinctrl_dev *pctldev, - unsigned func_selector, - unsigned group_selector) +static int wmt_pmx_set_mux(struct pinctrl_dev *pctldev, + unsigned func_selector, + unsigned group_selector) { struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); u32 pinnum = data->pins[group_selector].number; @@ -168,7 +168,7 @@ static struct pinmux_ops wmt_pinmux_ops = { .get_functions_count = wmt_pmx_get_functions_count, .get_function_name = wmt_pmx_get_function_name, .get_function_groups = wmt_pmx_get_function_groups, - .enable = wmt_pmx_enable, + .set_mux = wmt_pmx_set_mux, .gpio_disable_free = wmt_pmx_gpio_disable_free, .gpio_set_direction = wmt_pmx_gpio_set_direction, }; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 2dc8289e5dba..55d7b7b0f2e0 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -199,13 +199,14 @@ config REGULATOR_DA9210 interface. config REGULATOR_DA9211 - tristate "Dialog Semiconductor DA9211/DA9212 regulator" + tristate "Dialog Semiconductor DA9211/DA9212/DA9213/DA9214 regulator" depends on I2C select REGMAP_I2C help - Say y here to support for the Dialog Semiconductor DA9211/DA9212. - The DA9211/DA9212 is a multi-phase synchronous step down - converter 12A DC-DC Buck controlled through an I2C + Say y here to support for the Dialog Semiconductor DA9211/DA9212 + /DA9213/DA9214. + The DA9211/DA9212/DA9213/DA9214 is a multi-phase synchronous + step down converter 12A or 16A DC-DC Buck controlled through an I2C interface. config REGULATOR_DBX500_PRCMU @@ -240,6 +241,23 @@ config REGULATOR_GPIO and the platform has to provide a mapping of GPIO-states to target volts/amps. +config REGULATOR_HI6421 + tristate "HiSilicon Hi6421 PMIC voltage regulator support" + depends on MFD_HI6421_PMIC && OF + help + This driver provides support for the voltage regulators on the + HiSilicon Hi6421 PMU / Codec IC. + Hi6421 is a multi-function device which, on regulator part, provides + 21 general purpose LDOs, 3 dedicated LDOs, and 5 BUCKs. All + of them come with support to either ECO (idle) or sleep mode. + +config REGULATOR_ISL9305 + tristate "Intersil ISL9305 regulator" + depends on I2C + select REGMAP_I2C + help + This driver supports ISL9305 voltage regulator chip. + config REGULATOR_ISL6271A tristate "Intersil ISL6271A Power regulator" depends on I2C @@ -387,6 +405,15 @@ config REGULATOR_MAX77693 and one current regulator 'CHARGER'. This is suitable for Exynos-4x12 chips. +config REGULATOR_MAX77802 + tristate "Maxim 77802 regulator" + depends on MFD_MAX77686 + help + This driver controls a Maxim 77802 regulator + via I2C bus. The provided regulator is suitable for + Exynos5420/Exynos5800 SoCs to control various voltages. + It includes support for control of voltage and ramp speed. + config REGULATOR_MC13XXX_CORE tristate @@ -449,6 +476,25 @@ config REGULATOR_PFUZE100 Say y here to support the regulators found on the Freescale PFUZE100/PFUZE200 PMIC. +config REGULATOR_PWM + tristate "PWM voltage regulator" + depends on PWM + help + This driver supports PWM controlled voltage regulators. PWM + duty cycle can increase or decrease the voltage. + +config REGULATOR_QCOM_RPM + tristate "Qualcomm RPM regulator driver" + depends on MFD_QCOM_RPM + help + If you say yes to this option, support will be included for the + regulators exposed by the Resource Power Manager found in Qualcomm + 8660, 8960 and 8064 based devices. + + Say M here if you want to include support for the regulators on the + Qualcomm RPM as a module. The module will be named + "qcom_rpm-regulator". + config REGULATOR_RC5T583 tristate "RICOH RC5T583 Power regulators" depends on MFD_RC5T583 @@ -459,6 +505,22 @@ config REGULATOR_RC5T583 through regulator interface. The device supports multiple DCDC/LDO outputs which can be controlled by i2c communication. +config REGULATOR_RK808 + tristate "Rockchip RK808 Power regulators" + depends on MFD_RK808 + help + Select this option to enable the power regulator of ROCKCHIP + PMIC RK808. + This driver supports the control of different power rails of device + through regulator interface. The device supports multiple DCDC/LDO + outputs which can be controlled by i2c communication. + +config REGULATOR_RN5T618 + tristate "Ricoh RN5T618 voltage regulators" + depends on MFD_RN5T618 + help + Say y here to support the regulators found on Ricoh RN5T618 PMIC. + config REGULATOR_S2MPA01 tristate "Samsung S2MPA01 voltage regulator" depends on MFD_SEC_CORE @@ -483,11 +545,16 @@ config REGULATOR_S5M8767 via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and supports DVS mode with 8bits of output voltage control. -config REGULATOR_ST_PWM - tristate "STMicroelectronics PWM voltage regulator" - depends on ARCH_STI +config REGULATOR_SKY81452 + tristate "Skyworks Solutions SKY81452 voltage regulator" + depends on SKY81452 help - This driver supports ST's PWM controlled voltage regulators. + This driver supports Skyworks SKY81452 voltage output regulator + via I2C bus. SKY81452 has one voltage linear regulator can be + programmed from 4.5V to 20V. + + This driver can also be built as a module. If so, the module + will be called sky81452-regulator. config REGULATOR_TI_ABB tristate "TI Adaptive Body Bias on-chip LDO" diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index aa4a6aa7b558..1029ed39c512 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -32,7 +32,9 @@ obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o +obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o +obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o @@ -52,20 +54,25 @@ obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o +obj-$(CONFIG_REGULATOR_MAX77802) += max77802.o obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o +obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o +obj-$(CONFIG_REGULATOR_PWM) += pwm-regulator.o obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o +obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o +obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o -obj-$(CONFIG_REGULATOR_ST_PWM) += st-pwm.o +obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c index b47283f91e2d..8459b0b648cd 100644 --- a/drivers/regulator/as3711-regulator.c +++ b/drivers/regulator/as3711-regulator.c @@ -22,12 +22,10 @@ struct as3711_regulator_info { struct regulator_desc desc; - unsigned int max_uV; }; struct as3711_regulator { struct as3711_regulator_info *reg_info; - struct regulator_dev *rdev; }; /* @@ -132,39 +130,37 @@ static const struct regulator_linear_range as3711_dldo_ranges[] = { REGULATOR_LINEAR_RANGE(1750000, 0x20, 0x3f, 50000), }; -#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \ - [AS3711_REGULATOR_ ## _id] = { \ - .desc = { \ - .name = "as3711-regulator-" # _id, \ - .id = AS3711_REGULATOR_ ## _id, \ - .n_voltages = (_vmask + 1), \ - .ops = &as3711_ ## _sfx ## _ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .vsel_reg = AS3711_ ## _id ## _VOLTAGE, \ - .vsel_mask = _vmask << _vshift, \ - .enable_reg = AS3711_ ## _en_reg, \ - .enable_mask = BIT(_en_bit), \ - .min_uV = _min_uV, \ - .linear_ranges = as3711_ ## _sfx ## _ranges, \ - .n_linear_ranges = ARRAY_SIZE(as3711_ ## _sfx ## _ranges), \ - }, \ - .max_uV = _max_uV, \ +#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _sfx) \ + [AS3711_REGULATOR_ ## _id] = { \ + .desc = { \ + .name = "as3711-regulator-" # _id, \ + .id = AS3711_REGULATOR_ ## _id, \ + .n_voltages = (_vmask + 1), \ + .ops = &as3711_ ## _sfx ## _ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .vsel_reg = AS3711_ ## _id ## _VOLTAGE, \ + .vsel_mask = _vmask, \ + .enable_reg = AS3711_ ## _en_reg, \ + .enable_mask = BIT(_en_bit), \ + .linear_ranges = as3711_ ## _sfx ## _ranges, \ + .n_linear_ranges = ARRAY_SIZE(as3711_ ## _sfx ## _ranges), \ + }, \ } static struct as3711_regulator_info as3711_reg_info[] = { - AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd), - AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd), - AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd), - AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd), - AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo), - AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo), - AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), - AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), - AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), - AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), - AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), - AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), + AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, sd), + AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, sd), + AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, sd), + AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, sd), + AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, aldo), + AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, aldo), + AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, dldo), + AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, dldo), + AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, dldo), + AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, dldo), + AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, dldo), + AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, dldo), /* StepUp output voltage depends on supplying regulator */ }; @@ -263,7 +259,6 @@ static int as3711_regulator_probe(struct platform_device *pdev) ri->desc.name); return PTR_ERR(rdev); } - reg->rdev = rdev; } platform_set_drvdata(pdev, regs); return 0; diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 004aadb7bcc1..2e1010a34ddc 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -245,7 +245,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev) for (i = 0; i < AXP20X_REG_ID_MAX; i++) { init_data = axp20x_matches[i].init_data; - config.dev = &pdev->dev; + config.dev = pdev->dev.parent; config.init_data = init_data; config.regmap = axp20x->regmap; config.of_node = axp20x_matches[i].of_node; diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c index 5d1fd6f3d10a..fe6ac69549a6 100644 --- a/drivers/regulator/bcm590xx-regulator.c +++ b/drivers/regulator/bcm590xx-regulator.c @@ -202,7 +202,6 @@ static struct bcm590xx_info bcm590xx_regs[] = { struct bcm590xx_reg { struct regulator_desc *desc; struct bcm590xx *mfd; - struct bcm590xx_info **info; }; static int bcm590xx_get_vsel_register(int id) @@ -389,11 +388,6 @@ static int bcm590xx_probe(struct platform_device *pdev) if (!pmu->desc) return -ENOMEM; - pmu->info = devm_kzalloc(&pdev->dev, BCM590XX_NUM_REGS * - sizeof(struct bcm590xx_info *), GFP_KERNEL); - if (!pmu->info) - return -ENOMEM; - info = bcm590xx_regs; for (i = 0; i < BCM590XX_NUM_REGS; i++, info++) { @@ -403,8 +397,6 @@ static int bcm590xx_probe(struct platform_device *pdev) reg_data = NULL; /* Register the regulators */ - pmu->info[i] = info; - pmu->desc[i].name = info->name; pmu->desc[i].supply_name = info->vin_name; pmu->desc[i].id = i; diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a3c3785901f5..cd87c0c37034 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -102,7 +102,7 @@ static int _regulator_disable(struct regulator_dev *rdev); static int _regulator_get_voltage(struct regulator_dev *rdev); static int _regulator_get_current_limit(struct regulator_dev *rdev); static unsigned int _regulator_get_mode(struct regulator_dev *rdev); -static void _notifier_call_chain(struct regulator_dev *rdev, +static int _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data); static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV); @@ -839,7 +839,7 @@ static void print_constraints(struct regulator_dev *rdev) static int machine_constraints_voltage(struct regulator_dev *rdev, struct regulation_constraints *constraints) { - struct regulator_ops *ops = rdev->desc->ops; + const struct regulator_ops *ops = rdev->desc->ops; int ret; /* do we need to apply the constraint voltage */ @@ -938,7 +938,7 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, static int machine_constraints_current(struct regulator_dev *rdev, struct regulation_constraints *constraints) { - struct regulator_ops *ops = rdev->desc->ops; + const struct regulator_ops *ops = rdev->desc->ops; int ret; if (!constraints->min_uA && !constraints->max_uA) @@ -982,7 +982,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, const struct regulation_constraints *constraints) { int ret = 0; - struct regulator_ops *ops = rdev->desc->ops; + const struct regulator_ops *ops = rdev->desc->ops; if (constraints) rdev->constraints = kmemdup(constraints, sizeof(*constraints), @@ -1759,6 +1759,45 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) return 0; } +/** + * _regulator_enable_delay - a delay helper function + * @delay: time to delay in microseconds + * + * Delay for the requested amount of time as per the guidelines in: + * + * Documentation/timers/timers-howto.txt + * + * The assumption here is that regulators will never be enabled in + * atomic context and therefore sleeping functions can be used. + */ +static void _regulator_enable_delay(unsigned int delay) +{ + unsigned int ms = delay / 1000; + unsigned int us = delay % 1000; + + if (ms > 0) { + /* + * For small enough values, handle super-millisecond + * delays in the usleep_range() call below. + */ + if (ms < 20) + us += ms * 1000; + else + msleep(ms); + } + + /* + * Give the scheduler some room to coalesce with any other + * wakeup sources. For delays shorter than 10 us, don't even + * bother setting up high-resolution timers and just busy- + * loop. + */ + if (us >= 10) + usleep_range(us, us + 100); + else + udelay(us); +} + static int _regulator_do_enable(struct regulator_dev *rdev) { int ret, delay; @@ -1774,6 +1813,31 @@ static int _regulator_do_enable(struct regulator_dev *rdev) trace_regulator_enable(rdev_get_name(rdev)); + if (rdev->desc->off_on_delay) { + /* if needed, keep a distance of off_on_delay from last time + * this regulator was disabled. + */ + unsigned long start_jiffy = jiffies; + unsigned long intended, max_delay, remaining; + + max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); + intended = rdev->last_off_jiffy + max_delay; + + if (time_before(start_jiffy, intended)) { + /* calc remaining jiffies to deal with one-time + * timer wrapping. + * in case of multiple timer wrapping, either it can be + * detected by out-of-range remaining, or it cannot be + * detected and we gets a panelty of + * _regulator_enable_delay(). + */ + remaining = intended - start_jiffy; + if (remaining <= max_delay) + _regulator_enable_delay( + jiffies_to_usecs(remaining)); + } + } + if (rdev->ena_pin) { ret = regulator_ena_gpio_ctrl(rdev, true); if (ret < 0) @@ -1792,40 +1856,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev) * together. */ trace_regulator_enable_delay(rdev_get_name(rdev)); - /* - * Delay for the requested amount of time as per the guidelines in: - * - * Documentation/timers/timers-howto.txt - * - * The assumption here is that regulators will never be enabled in - * atomic context and therefore sleeping functions can be used. - */ - if (delay) { - unsigned int ms = delay / 1000; - unsigned int us = delay % 1000; - - if (ms > 0) { - /* - * For small enough values, handle super-millisecond - * delays in the usleep_range() call below. - */ - if (ms < 20) - us += ms * 1000; - else - msleep(ms); - } - - /* - * Give the scheduler some room to coalesce with any other - * wakeup sources. For delays shorter than 10 us, don't even - * bother setting up high-resolution timers and just busy- - * loop. - */ - if (us >= 10) - usleep_range(us, us + 100); - else - udelay(us); - } + _regulator_enable_delay(delay); trace_regulator_enable_complete(rdev_get_name(rdev)); @@ -1919,6 +1950,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev) return ret; } + /* cares about last_off_jiffy only if off_on_delay is required by + * device. + */ + if (rdev->desc->off_on_delay) + rdev->last_off_jiffy = jiffies; + trace_regulator_disable_complete(rdev_get_name(rdev)); return 0; @@ -2208,9 +2245,9 @@ EXPORT_SYMBOL_GPL(regulator_count_voltages); */ int regulator_list_voltage(struct regulator *regulator, unsigned selector) { - struct regulator_dev *rdev = regulator->rdev; - struct regulator_ops *ops = rdev->desc->ops; - int ret; + struct regulator_dev *rdev = regulator->rdev; + const struct regulator_ops *ops = rdev->desc->ops; + int ret; if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) return rdev->desc->fixed_uV; @@ -2270,8 +2307,8 @@ int regulator_get_hardware_vsel_register(struct regulator *regulator, unsigned *vsel_reg, unsigned *vsel_mask) { - struct regulator_dev *rdev = regulator->rdev; - struct regulator_ops *ops = rdev->desc->ops; + struct regulator_dev *rdev = regulator->rdev; + const struct regulator_ops *ops = rdev->desc->ops; if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) return -EOPNOTSUPP; @@ -2297,8 +2334,8 @@ EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); int regulator_list_hardware_vsel(struct regulator *regulator, unsigned selector) { - struct regulator_dev *rdev = regulator->rdev; - struct regulator_ops *ops = rdev->desc->ops; + struct regulator_dev *rdev = regulator->rdev; + const struct regulator_ops *ops = rdev->desc->ops; if (selector >= rdev->desc->n_voltages) return -EINVAL; @@ -2369,6 +2406,55 @@ int regulator_is_supported_voltage(struct regulator *regulator, } EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); +static int _regulator_call_set_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV, + unsigned *selector) +{ + struct pre_voltage_change_data data; + int ret; + + data.old_uV = _regulator_get_voltage(rdev); + data.min_uV = min_uV; + data.max_uV = max_uV; + ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, + &data); + if (ret & NOTIFY_STOP_MASK) + return -EINVAL; + + ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); + if (ret >= 0) + return ret; + + _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, + (void *)data.old_uV); + + return ret; +} + +static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, + int uV, unsigned selector) +{ + struct pre_voltage_change_data data; + int ret; + + data.old_uV = _regulator_get_voltage(rdev); + data.min_uV = uV; + data.max_uV = uV; + ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, + &data); + if (ret & NOTIFY_STOP_MASK) + return -EINVAL; + + ret = rdev->desc->ops->set_voltage_sel(rdev, selector); + if (ret >= 0) + return ret; + + _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, + (void *)data.old_uV); + + return ret; +} + static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { @@ -2396,8 +2482,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } if (rdev->desc->ops->set_voltage) { - ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, - &selector); + ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, + &selector); if (ret >= 0) { if (rdev->desc->ops->list_voltage) @@ -2432,8 +2518,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, if (old_selector == selector) ret = 0; else - ret = rdev->desc->ops->set_voltage_sel( - rdev, ret); + ret = _regulator_call_set_voltage_sel( + rdev, best_val, selector); } else { ret = -EINVAL; } @@ -2572,8 +2658,8 @@ EXPORT_SYMBOL_GPL(regulator_set_voltage); int regulator_set_voltage_time(struct regulator *regulator, int old_uV, int new_uV) { - struct regulator_dev *rdev = regulator->rdev; - struct regulator_ops *ops = rdev->desc->ops; + struct regulator_dev *rdev = regulator->rdev; + const struct regulator_ops *ops = rdev->desc->ops; int old_sel = -1; int new_sel = -1; int voltage; @@ -3079,11 +3165,11 @@ EXPORT_SYMBOL_GPL(regulator_unregister_notifier); /* notify regulator consumers and downstream regulator consumers. * Note mutex must be held by caller. */ -static void _notifier_call_chain(struct regulator_dev *rdev, +static int _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data) { /* call rdev chain first */ - blocking_notifier_call_chain(&rdev->notifier, event, data); + return blocking_notifier_call_chain(&rdev->notifier, event, data); } /** @@ -3336,9 +3422,9 @@ EXPORT_SYMBOL_GPL(regulator_mode_to_status); */ static int add_regulator_attributes(struct regulator_dev *rdev) { - struct device *dev = &rdev->dev; - struct regulator_ops *ops = rdev->desc->ops; - int status = 0; + struct device *dev = &rdev->dev; + const struct regulator_ops *ops = rdev->desc->ops; + int status = 0; /* some attributes need specific methods to be displayed */ if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || @@ -3516,12 +3602,17 @@ regulator_register(const struct regulator_desc *regulator_desc, return ERR_PTR(-EINVAL); } - init_data = config->init_data; - rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); if (rdev == NULL) return ERR_PTR(-ENOMEM); + init_data = regulator_of_get_init_data(dev, regulator_desc, + &rdev->dev.of_node); + if (!init_data) { + init_data = config->init_data; + rdev->dev.of_node = of_node_get(config->of_node); + } + mutex_lock(®ulator_list_mutex); mutex_init(&rdev->mutex); @@ -3548,7 +3639,6 @@ regulator_register(const struct regulator_desc *regulator_desc, /* register with sysfs */ rdev->dev.class = ®ulator_class; - rdev->dev.of_node = of_node_get(config->of_node); rdev->dev.parent = dev; dev_set_name(&rdev->dev, "regulator.%d", atomic_inc_return(®ulator_no) - 1); @@ -3905,7 +3995,7 @@ core_initcall(regulator_init); static int __init regulator_init_complete(void) { struct regulator_dev *rdev; - struct regulator_ops *ops; + const struct regulator_ops *ops; struct regulation_constraints *c; int enabled, ret; diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index 1482adafa1ad..c78d2106d6cb 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -1,5 +1,5 @@ /* - * da9211-regulator.c - Regulator device driver for DA9211 + * da9211-regulator.c - Regulator device driver for DA9211/DA9213 * Copyright (C) 2014 Dialog Semiconductor Ltd. * * This library is free software; you can redistribute it and/or @@ -24,9 +24,14 @@ #include <linux/regmap.h> #include <linux/irq.h> #include <linux/interrupt.h> +#include <linux/regulator/of_regulator.h> #include <linux/regulator/da9211.h> #include "da9211-regulator.h" +/* DEVICE IDs */ +#define DA9211_DEVICE_ID 0x22 +#define DA9213_DEVICE_ID 0x23 + #define DA9211_BUCK_MODE_SLEEP 1 #define DA9211_BUCK_MODE_SYNC 2 #define DA9211_BUCK_MODE_AUTO 3 @@ -42,6 +47,7 @@ struct da9211 { struct regulator_dev *rdev[DA9211_MAX_REGULATORS]; int num_regulator; int chip_irq; + int chip_id; }; static const struct regmap_range_cfg da9211_regmap_range[] = { @@ -52,14 +58,14 @@ static const struct regmap_range_cfg da9211_regmap_range[] = { .window_start = 0, .window_len = 256, .range_min = 0, - .range_max = 2*256, + .range_max = 5*128, }, }; static const struct regmap_config da9211_regmap_config = { .reg_bits = 8, .val_bits = 8, - .max_register = 2 * 256, + .max_register = 5 * 128, .ranges = da9211_regmap_range, .num_ranges = ARRAY_SIZE(da9211_regmap_range), }; @@ -69,11 +75,20 @@ static const struct regmap_config da9211_regmap_config = { #define DA9211_MAX_MV 1570 #define DA9211_STEP_MV 10 -/* Current limits for buck (uA) indices corresponds with register values */ +/* Current limits for DA9211 buck (uA) indices + * corresponds with register values + */ static const int da9211_current_limits[] = { 2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000, 4600000, 4800000, 5000000 }; +/* Current limits for DA9213 buck (uA) indices + * corresponds with register values + */ +static const int da9213_current_limits[] = { + 3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000, + 4600000, 4800000, 5000000, 5200000, 5400000, 5600000, 5800000, 6000000 +}; static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev) { @@ -129,12 +144,26 @@ static int da9211_set_current_limit(struct regulator_dev *rdev, int min, { int id = rdev_get_id(rdev); struct da9211 *chip = rdev_get_drvdata(rdev); - int i; + int i, max_size; + const int *current_limits; + + switch (chip->chip_id) { + case DA9211: + current_limits = da9211_current_limits; + max_size = ARRAY_SIZE(da9211_current_limits)-1; + break; + case DA9213: + current_limits = da9213_current_limits; + max_size = ARRAY_SIZE(da9213_current_limits)-1; + break; + default: + return -EINVAL; + } /* search for closest to maximum */ - for (i = ARRAY_SIZE(da9211_current_limits)-1; i >= 0; i--) { - if (min <= da9211_current_limits[i] && - max >= da9211_current_limits[i]) { + for (i = max_size; i >= 0; i--) { + if (min <= current_limits[i] && + max >= current_limits[i]) { return regmap_update_bits(chip->regmap, DA9211_REG_BUCK_ILIM, (0x0F << id*4), (i << id*4)); @@ -150,14 +179,28 @@ static int da9211_get_current_limit(struct regulator_dev *rdev) struct da9211 *chip = rdev_get_drvdata(rdev); unsigned int data; int ret; + const int *current_limits; + + switch (chip->chip_id) { + case DA9211: + current_limits = da9211_current_limits; + break; + case DA9213: + current_limits = da9213_current_limits; + break; + default: + return -EINVAL; + } ret = regmap_read(chip->regmap, DA9211_REG_BUCK_ILIM, &data); if (ret < 0) return ret; - /* select one of 16 values: 0000 (2000mA) to 1111 (5000mA) */ + /* select one of 16 values: 0000 (2000mA or 3000mA) + * to 1111 (5000mA or 6000mA). + */ data = (data >> id*4) & 0x0F; - return da9211_current_limits[data]; + return current_limits[data]; } static struct regulator_ops da9211_buck_ops = { @@ -194,6 +237,59 @@ static struct regulator_desc da9211_regulators[] = { DA9211_BUCK(BUCKB), }; +#ifdef CONFIG_OF +static struct of_regulator_match da9211_matches[] = { + [DA9211_ID_BUCKA] = { .name = "BUCKA" }, + [DA9211_ID_BUCKB] = { .name = "BUCKB" }, + }; + +static struct da9211_pdata *da9211_parse_regulators_dt( + struct device *dev) +{ + struct da9211_pdata *pdata; + struct device_node *node; + int i, num, n; + + node = of_get_child_by_name(dev->of_node, "regulators"); + if (!node) { + dev_err(dev, "regulators node not found\n"); + return ERR_PTR(-ENODEV); + } + + num = of_regulator_match(dev, node, da9211_matches, + ARRAY_SIZE(da9211_matches)); + of_node_put(node); + if (num < 0) { + dev_err(dev, "Failed to match regulators\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + pdata->num_buck = num; + + n = 0; + for (i = 0; i < ARRAY_SIZE(da9211_matches); i++) { + if (!da9211_matches[i].init_data) + continue; + + pdata->init_data[n] = da9211_matches[i].init_data; + + n++; + } + + return pdata; +} +#else +static struct da9211_pdata *da9211_parse_regulators_dt( + struct device *dev) +{ + return ERR_PTR(-ENODEV); +} +#endif + static irqreturn_t da9211_irq_handler(int irq, void *data) { struct da9211 *chip = data; @@ -264,13 +360,11 @@ static int da9211_regulator_init(struct da9211 *chip) } for (i = 0; i < chip->num_regulator; i++) { - if (chip->pdata) - config.init_data = - &(chip->pdata->init_data[i]); - + config.init_data = chip->pdata->init_data[i]; config.dev = chip->dev; config.driver_data = chip; config.regmap = chip->regmap; + config.of_node = chip->dev->of_node; chip->rdev[i] = devm_regulator_register(chip->dev, &da9211_regulators[i], &config); @@ -282,7 +376,7 @@ static int da9211_regulator_init(struct da9211 *chip) if (chip->chip_irq != 0) { ret = regmap_update_bits(chip->regmap, - DA9211_REG_MASK_B, DA9211_M_OV_CURR_A << i, 1); + DA9211_REG_MASK_B, DA9211_M_OV_CURR_A << i, 0); if (ret < 0) { dev_err(chip->dev, "Failed to update mask reg: %d\n", ret); @@ -293,6 +387,7 @@ static int da9211_regulator_init(struct da9211 *chip) return 0; } + /* * I2C driver interface functions */ @@ -301,14 +396,17 @@ static int da9211_i2c_probe(struct i2c_client *i2c, { struct da9211 *chip; int error, ret; + unsigned int data; chip = devm_kzalloc(&i2c->dev, sizeof(struct da9211), GFP_KERNEL); + if (!chip) + return -ENOMEM; chip->dev = &i2c->dev; chip->regmap = devm_regmap_init_i2c(i2c, &da9211_regmap_config); if (IS_ERR(chip->regmap)) { error = PTR_ERR(chip->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + dev_err(chip->dev, "Failed to allocate register map: %d\n", error); return error; } @@ -316,11 +414,33 @@ static int da9211_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, chip); chip->pdata = i2c->dev.platform_data; - if (!chip->pdata) { - dev_err(&i2c->dev, "No platform init data supplied\n"); + + ret = regmap_read(chip->regmap, DA9211_REG_DEVICE_ID, &data); + if (ret < 0) { + dev_err(chip->dev, "Failed to read DEVICE_ID reg: %d\n", ret); + return ret; + } + + switch (data) { + case DA9211_DEVICE_ID: + chip->chip_id = DA9211; + break; + case DA9213_DEVICE_ID: + chip->chip_id = DA9213; + break; + default: + dev_err(chip->dev, "Unsupported device id = 0x%x.\n", data); return -ENODEV; } + if (!chip->pdata) + chip->pdata = da9211_parse_regulators_dt(chip->dev); + + if (IS_ERR(chip->pdata)) { + dev_err(chip->dev, "No regulators defined for the platform\n"); + return PTR_ERR(chip->pdata); + } + chip->chip_irq = i2c->irq; if (chip->chip_irq != 0) { @@ -340,22 +460,32 @@ static int da9211_i2c_probe(struct i2c_client *i2c, ret = da9211_regulator_init(chip); if (ret < 0) - dev_err(&i2c->dev, "Failed to initialize regulator: %d\n", ret); + dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret); return ret; } static const struct i2c_device_id da9211_i2c_id[] = { - {"da9211", 0}, + {"da9211", DA9211}, + {"da9213", DA9213}, {}, }; - MODULE_DEVICE_TABLE(i2c, da9211_i2c_id); +#ifdef CONFIG_OF +static const struct of_device_id da9211_dt_ids[] = { + { .compatible = "dlg,da9211", .data = &da9211_i2c_id[0] }, + { .compatible = "dlg,da9213", .data = &da9211_i2c_id[1] }, + {}, +}; +MODULE_DEVICE_TABLE(of, da9211_dt_ids); +#endif + static struct i2c_driver da9211_regulator_driver = { .driver = { .name = "da9211", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(da9211_dt_ids), }, .probe = da9211_i2c_probe, .id_table = da9211_i2c_id, @@ -364,5 +494,5 @@ static struct i2c_driver da9211_regulator_driver = { module_i2c_driver(da9211_regulator_driver); MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>"); -MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211"); +MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211/DA9213"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/da9211-regulator.h b/drivers/regulator/da9211-regulator.h index 88b1769e8058..93fa9df2721c 100644 --- a/drivers/regulator/da9211-regulator.h +++ b/drivers/regulator/da9211-regulator.h @@ -1,5 +1,5 @@ /* - * da9211-regulator.h - Regulator definitions for DA9211 + * da9211-regulator.h - Regulator definitions for DA9211/DA9213 * Copyright (C) 2014 Dialog Semiconductor Ltd. * * This library is free software; you can redistribute it and/or @@ -53,12 +53,15 @@ /* BUCK Phase Selection*/ #define DA9211_REG_CONFIG_E 0x147 +/* Device ID */ +#define DA9211_REG_DEVICE_ID 0x201 + /* * Registers bits */ /* DA9211_REG_PAGE_CON (addr=0x00) */ #define DA9211_REG_PAGE_SHIFT 1 -#define DA9211_REG_PAGE_MASK 0x02 +#define DA9211_REG_PAGE_MASK 0x06 /* On I2C registers 0x00 - 0xFF */ #define DA9211_REG_PAGE0 0 /* On I2C registers 0x100 - 0x1FF */ diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 714fd9a89aa1..f8e4257aef92 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -18,6 +18,8 @@ #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/of_device.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/regmap.h> @@ -50,6 +52,11 @@ #define FAN53555_NVOLTAGES 64 /* Numbers of voltages */ +enum fan53555_vendor { + FAN53555_VENDOR_FAIRCHILD = 0, + FAN53555_VENDOR_SILERGY, +}; + /* IC Type */ enum { FAN53555_CHIP_ID_00 = 0, @@ -60,7 +67,12 @@ enum { FAN53555_CHIP_ID_05, }; +enum { + SILERGY_SYR82X = 8, +}; + struct fan53555_device_info { + enum fan53555_vendor vendor; struct regmap *regmap; struct device *dev; struct regulator_desc desc; @@ -135,6 +147,38 @@ static unsigned int fan53555_get_mode(struct regulator_dev *rdev) return REGULATOR_MODE_NORMAL; } +static int slew_rates[] = { + 64000, + 32000, + 16000, + 8000, + 4000, + 2000, + 1000, + 500, +}; + +static int fan53555_set_ramp(struct regulator_dev *rdev, int ramp) +{ + struct fan53555_device_info *di = rdev_get_drvdata(rdev); + int regval = -1, i; + + for (i = 0; i < ARRAY_SIZE(slew_rates); i++) { + if (ramp <= slew_rates[i]) + regval = i; + else + break; + } + + if (regval < 0) { + dev_err(di->dev, "unsupported ramp value %d\n", ramp); + return -EINVAL; + } + + return regmap_update_bits(di->regmap, FAN53555_CONTROL, + CTL_SLEW_MASK, regval << CTL_SLEW_SHIFT); +} + static struct regulator_ops fan53555_regulator_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -146,8 +190,50 @@ static struct regulator_ops fan53555_regulator_ops = { .is_enabled = regulator_is_enabled_regmap, .set_mode = fan53555_set_mode, .get_mode = fan53555_get_mode, + .set_ramp_delay = fan53555_set_ramp, }; +static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) +{ + /* Init voltage range and step */ + switch (di->chip_id) { + case FAN53555_CHIP_ID_00: + case FAN53555_CHIP_ID_01: + case FAN53555_CHIP_ID_03: + case FAN53555_CHIP_ID_05: + di->vsel_min = 600000; + di->vsel_step = 10000; + break; + case FAN53555_CHIP_ID_04: + di->vsel_min = 603000; + di->vsel_step = 12826; + break; + default: + dev_err(di->dev, + "Chip ID %d not supported!\n", di->chip_id); + return -EINVAL; + } + + return 0; +} + +static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di) +{ + /* Init voltage range and step */ + switch (di->chip_id) { + case SILERGY_SYR82X: + di->vsel_min = 712500; + di->vsel_step = 12500; + break; + default: + dev_err(di->dev, + "Chip ID %d not supported!\n", di->chip_id); + return -EINVAL; + } + + return 0; +} + /* For 00,01,03,05 options: * VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V. * For 04 option: @@ -156,7 +242,7 @@ static struct regulator_ops fan53555_regulator_ops = { static int fan53555_device_setup(struct fan53555_device_info *di, struct fan53555_platform_data *pdata) { - unsigned int reg, data, mask; + int ret = 0; /* Setup voltage control register */ switch (pdata->sleep_vsel_id) { @@ -172,33 +258,20 @@ static int fan53555_device_setup(struct fan53555_device_info *di, dev_err(di->dev, "Invalid VSEL ID!\n"); return -EINVAL; } - /* Init voltage range and step */ - switch (di->chip_id) { - case FAN53555_CHIP_ID_00: - case FAN53555_CHIP_ID_01: - case FAN53555_CHIP_ID_03: - case FAN53555_CHIP_ID_05: - di->vsel_min = 600000; - di->vsel_step = 10000; + + switch (di->vendor) { + case FAN53555_VENDOR_FAIRCHILD: + ret = fan53555_voltages_setup_fairchild(di); break; - case FAN53555_CHIP_ID_04: - di->vsel_min = 603000; - di->vsel_step = 12826; + case FAN53555_VENDOR_SILERGY: + ret = fan53555_voltages_setup_silergy(di); break; default: - dev_err(di->dev, - "Chip ID[%d]\n not supported!\n", di->chip_id); + dev_err(di->dev, "vendor %d not supported!\n", di->vendor); return -EINVAL; } - /* Init slew rate */ - if (pdata->slew_rate & 0x7) - di->slew_rate = pdata->slew_rate; - else - di->slew_rate = FAN53555_SLEW_RATE_64MV; - reg = FAN53555_CONTROL; - data = di->slew_rate << CTL_SLEW_SHIFT; - mask = CTL_SLEW_MASK; - return regmap_update_bits(di->regmap, reg, mask, data); + + return ret; } static int fan53555_regulator_register(struct fan53555_device_info *di, @@ -207,6 +280,7 @@ static int fan53555_regulator_register(struct fan53555_device_info *di, struct regulator_desc *rdesc = &di->desc; rdesc->name = "fan53555-reg"; + rdesc->supply_name = "vin"; rdesc->ops = &fan53555_regulator_ops; rdesc->type = REGULATOR_VOLTAGE; rdesc->n_voltages = FAN53555_NVOLTAGES; @@ -227,9 +301,46 @@ static struct regmap_config fan53555_regmap_config = { .val_bits = 8, }; +static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev, + struct device_node *np) +{ + struct fan53555_platform_data *pdata; + int ret; + u32 tmp; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + pdata->regulator = of_get_regulator_init_data(dev, np); + + ret = of_property_read_u32(np, "fcs,suspend-voltage-selector", + &tmp); + if (!ret) + pdata->sleep_vsel_id = tmp; + + return pdata; +} + +static const struct of_device_id fan53555_dt_ids[] = { + { + .compatible = "fcs,fan53555", + .data = (void *)FAN53555_VENDOR_FAIRCHILD + }, { + .compatible = "silergy,syr827", + .data = (void *)FAN53555_VENDOR_SILERGY, + }, { + .compatible = "silergy,syr828", + .data = (void *)FAN53555_VENDOR_SILERGY, + }, + { } +}; +MODULE_DEVICE_TABLE(of, fan53555_dt_ids); + static int fan53555_regulator_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device_node *np = client->dev.of_node; struct fan53555_device_info *di; struct fan53555_platform_data *pdata; struct regulator_config config = { }; @@ -237,6 +348,9 @@ static int fan53555_regulator_probe(struct i2c_client *client, int ret; pdata = dev_get_platdata(&client->dev); + if (!pdata) + pdata = fan53555_parse_dt(&client->dev, np); + if (!pdata || !pdata->regulator) { dev_err(&client->dev, "Platform data not found!\n"); return -ENODEV; @@ -247,13 +361,35 @@ static int fan53555_regulator_probe(struct i2c_client *client, if (!di) return -ENOMEM; + di->regulator = pdata->regulator; + if (client->dev.of_node) { + const struct of_device_id *match; + + match = of_match_device(of_match_ptr(fan53555_dt_ids), + &client->dev); + if (!match) + return -ENODEV; + + di->vendor = (unsigned long) match->data; + } else { + /* if no ramp constraint set, get the pdata ramp_delay */ + if (!di->regulator->constraints.ramp_delay) { + int slew_idx = (pdata->slew_rate & 0x7) + ? pdata->slew_rate : 0; + + di->regulator->constraints.ramp_delay + = slew_rates[slew_idx]; + } + + di->vendor = id->driver_data; + } + di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); if (IS_ERR(di->regmap)) { dev_err(&client->dev, "Failed to allocate regmap!\n"); return PTR_ERR(di->regmap); } di->dev = &client->dev; - di->regulator = pdata->regulator; i2c_set_clientdata(client, di); /* Get chip ID */ ret = regmap_read(di->regmap, FAN53555_ID1, &val); @@ -282,6 +418,8 @@ static int fan53555_regulator_probe(struct i2c_client *client, config.init_data = di->regulator; config.regmap = di->regmap; config.driver_data = di; + config.of_node = np; + ret = fan53555_regulator_register(di, &config); if (ret < 0) dev_err(&client->dev, "Failed to register regulator!\n"); @@ -290,13 +428,20 @@ static int fan53555_regulator_probe(struct i2c_client *client, } static const struct i2c_device_id fan53555_id[] = { - {"fan53555", -1}, + { + .name = "fan53555", + .driver_data = FAN53555_VENDOR_FAIRCHILD + }, { + .name = "syr82x", + .driver_data = FAN53555_VENDOR_SILERGY + }, { }, }; static struct i2c_driver fan53555_regulator_driver = { .driver = { .name = "fan53555-regulator", + .of_match_table = of_match_ptr(fan53555_dt_ids), }, .probe = fan53555_regulator_probe, .id_table = fan53555_id, diff --git a/drivers/regulator/hi6421-regulator.c b/drivers/regulator/hi6421-regulator.c new file mode 100644 index 000000000000..156d0d1a55f1 --- /dev/null +++ b/drivers/regulator/hi6421-regulator.c @@ -0,0 +1,634 @@ +/* + * Device driver for regulators in Hi6421 IC + * + * Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd. + * http://www.hisilicon.com + * Copyright (c) <2013-2014> Linaro Ltd. + * http://www.linaro.org + * + * Author: Guodong Xu <guodong.xu@linaro.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/mfd/hi6421-pmic.h> + +/* + * struct hi6421_regulator_pdata - Hi6421 regulator data of platform device + * @lock: mutex to serialize regulator enable + */ +struct hi6421_regulator_pdata { + struct mutex lock; +}; + +/* + * struct hi6421_regulator_info - hi6421 regulator information + * @desc: regulator description + * @mode_mask: ECO mode bitmask of LDOs; for BUCKs, this masks sleep + * @eco_microamp: eco mode load upper limit (in uA), valid for LDOs only + */ +struct hi6421_regulator_info { + struct regulator_desc desc; + u8 mode_mask; + u32 eco_microamp; +}; + +/* HI6421 regulators */ +enum hi6421_regulator_id { + HI6421_LDO0, + HI6421_LDO1, + HI6421_LDO2, + HI6421_LDO3, + HI6421_LDO4, + HI6421_LDO5, + HI6421_LDO6, + HI6421_LDO7, + HI6421_LDO8, + HI6421_LDO9, + HI6421_LDO10, + HI6421_LDO11, + HI6421_LDO12, + HI6421_LDO13, + HI6421_LDO14, + HI6421_LDO15, + HI6421_LDO16, + HI6421_LDO17, + HI6421_LDO18, + HI6421_LDO19, + HI6421_LDO20, + HI6421_LDOAUDIO, + HI6421_BUCK0, + HI6421_BUCK1, + HI6421_BUCK2, + HI6421_BUCK3, + HI6421_BUCK4, + HI6421_BUCK5, + HI6421_NUM_REGULATORS, +}; + +#define HI6421_REGULATOR_OF_MATCH(_name, id) \ +{ \ + .name = #_name, \ + .driver_data = (void *) HI6421_##id, \ +} + +static struct of_regulator_match hi6421_regulator_match[] = { + HI6421_REGULATOR_OF_MATCH(hi6421_vout0, LDO0), + HI6421_REGULATOR_OF_MATCH(hi6421_vout1, LDO1), + HI6421_REGULATOR_OF_MATCH(hi6421_vout2, LDO2), + HI6421_REGULATOR_OF_MATCH(hi6421_vout3, LDO3), + HI6421_REGULATOR_OF_MATCH(hi6421_vout4, LDO4), + HI6421_REGULATOR_OF_MATCH(hi6421_vout5, LDO5), + HI6421_REGULATOR_OF_MATCH(hi6421_vout6, LDO6), + HI6421_REGULATOR_OF_MATCH(hi6421_vout7, LDO7), + HI6421_REGULATOR_OF_MATCH(hi6421_vout8, LDO8), + HI6421_REGULATOR_OF_MATCH(hi6421_vout9, LDO9), + HI6421_REGULATOR_OF_MATCH(hi6421_vout10, LDO10), + HI6421_REGULATOR_OF_MATCH(hi6421_vout11, LDO11), + HI6421_REGULATOR_OF_MATCH(hi6421_vout12, LDO12), + HI6421_REGULATOR_OF_MATCH(hi6421_vout13, LDO13), + HI6421_REGULATOR_OF_MATCH(hi6421_vout14, LDO14), + HI6421_REGULATOR_OF_MATCH(hi6421_vout15, LDO15), + HI6421_REGULATOR_OF_MATCH(hi6421_vout16, LDO16), + HI6421_REGULATOR_OF_MATCH(hi6421_vout17, LDO17), + HI6421_REGULATOR_OF_MATCH(hi6421_vout18, LDO18), + HI6421_REGULATOR_OF_MATCH(hi6421_vout19, LDO19), + HI6421_REGULATOR_OF_MATCH(hi6421_vout20, LDO20), + HI6421_REGULATOR_OF_MATCH(hi6421_vout_audio, LDOAUDIO), + HI6421_REGULATOR_OF_MATCH(hi6421_buck0, BUCK0), + HI6421_REGULATOR_OF_MATCH(hi6421_buck1, BUCK1), + HI6421_REGULATOR_OF_MATCH(hi6421_buck2, BUCK2), + HI6421_REGULATOR_OF_MATCH(hi6421_buck3, BUCK3), + HI6421_REGULATOR_OF_MATCH(hi6421_buck4, BUCK4), + HI6421_REGULATOR_OF_MATCH(hi6421_buck5, BUCK5), +}; + +/* LDO 0, 4~7, 9~14, 16~20 have same voltage table. */ +static const unsigned int ldo_0_voltages[] = { + 1500000, 1800000, 2400000, 2500000, + 2600000, 2700000, 2850000, 3000000, +}; + +/* LDO 8, 15 have same voltage table. */ +static const unsigned int ldo_8_voltages[] = { + 1500000, 1800000, 2400000, 2600000, + 2700000, 2850000, 3000000, 3300000, +}; + +/* Ranges are sorted in ascending order. */ +static const struct regulator_linear_range ldo_audio_volt_range[] = { + REGULATOR_LINEAR_RANGE(2800000, 0, 3, 50000), + REGULATOR_LINEAR_RANGE(3000000, 4, 7, 100000), +}; + +static const unsigned int buck_3_voltages[] = { + 950000, 1050000, 1100000, 1117000, + 1134000, 1150000, 1167000, 1200000, +}; + +static const unsigned int buck_4_voltages[] = { + 1150000, 1200000, 1250000, 1350000, + 1700000, 1800000, 1900000, 2000000, +}; + +static const unsigned int buck_5_voltages[] = { + 1150000, 1200000, 1250000, 1350000, + 1600000, 1700000, 1800000, 1900000, +}; + +static const struct regulator_ops hi6421_ldo_ops; +static const struct regulator_ops hi6421_ldo_linear_ops; +static const struct regulator_ops hi6421_ldo_linear_range_ops; +static const struct regulator_ops hi6421_buck012_ops; +static const struct regulator_ops hi6421_buck345_ops; + +#define HI6421_LDO_ENABLE_TIME (350) +/* + * _id - LDO id name string + * v_table - voltage table + * vreg - voltage select register + * vmask - voltage select mask + * ereg - enable register + * emask - enable mask + * odelay - off/on delay time in uS + * ecomask - eco mode mask + * ecoamp - eco mode load uppler limit in uA + */ +#define HI6421_LDO(_id, v_table, vreg, vmask, ereg, emask, \ + odelay, ecomask, ecoamp) \ + [HI6421_##_id] = { \ + .desc = { \ + .name = #_id, \ + .ops = &hi6421_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = HI6421_##_id, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(v_table), \ + .volt_table = v_table, \ + .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \ + .vsel_mask = vmask, \ + .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \ + .enable_mask = emask, \ + .enable_time = HI6421_LDO_ENABLE_TIME, \ + .off_on_delay = odelay, \ + }, \ + .mode_mask = ecomask, \ + .eco_microamp = ecoamp, \ + } + +/* HI6421 LDO1~3 are linear voltage regulators at fixed uV_step + * + * _id - LDO id name string + * _min_uV - minimum voltage supported in uV + * n_volt - number of votages available + * vstep - voltage increase in each linear step in uV + * vreg - voltage select register + * vmask - voltage select mask + * ereg - enable register + * emask - enable mask + * odelay - off/on delay time in uS + * ecomask - eco mode mask + * ecoamp - eco mode load uppler limit in uA + */ +#define HI6421_LDO_LINEAR(_id, _min_uV, n_volt, vstep, vreg, vmask, \ + ereg, emask, odelay, ecomask, ecoamp) \ + [HI6421_##_id] = { \ + .desc = { \ + .name = #_id, \ + .ops = &hi6421_ldo_linear_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = HI6421_##_id, \ + .owner = THIS_MODULE, \ + .min_uV = _min_uV, \ + .n_voltages = n_volt, \ + .uV_step = vstep, \ + .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \ + .vsel_mask = vmask, \ + .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \ + .enable_mask = emask, \ + .enable_time = HI6421_LDO_ENABLE_TIME, \ + .off_on_delay = odelay, \ + }, \ + .mode_mask = ecomask, \ + .eco_microamp = ecoamp, \ + } + +/* HI6421 LDOAUDIO is a linear voltage regulator with two 4-step ranges + * + * _id - LDO id name string + * n_volt - number of votages available + * volt_ranges - array of regulator_linear_range + * vstep - voltage increase in each linear step in uV + * vreg - voltage select register + * vmask - voltage select mask + * ereg - enable register + * emask - enable mask + * odelay - off/on delay time in uS + * ecomask - eco mode mask + * ecoamp - eco mode load uppler limit in uA + */ +#define HI6421_LDO_LINEAR_RANGE(_id, n_volt, volt_ranges, vreg, vmask, \ + ereg, emask, odelay, ecomask, ecoamp) \ + [HI6421_##_id] = { \ + .desc = { \ + .name = #_id, \ + .ops = &hi6421_ldo_linear_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = HI6421_##_id, \ + .owner = THIS_MODULE, \ + .n_voltages = n_volt, \ + .linear_ranges = volt_ranges, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \ + .vsel_mask = vmask, \ + .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \ + .enable_mask = emask, \ + .enable_time = HI6421_LDO_ENABLE_TIME, \ + .off_on_delay = odelay, \ + }, \ + .mode_mask = ecomask, \ + .eco_microamp = ecoamp, \ + } + +/* HI6421 BUCK0/1/2 are linear voltage regulators at fixed uV_step + * + * _id - BUCK0/1/2 id name string + * vreg - voltage select register + * vmask - voltage select mask + * ereg - enable register + * emask - enable mask + * sleepmask - mask of sleep mode + * etime - enable time + * odelay - off/on delay time in uS + */ +#define HI6421_BUCK012(_id, vreg, vmask, ereg, emask, sleepmask, \ + etime, odelay) \ + [HI6421_##_id] = { \ + .desc = { \ + .name = #_id, \ + .ops = &hi6421_buck012_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = HI6421_##_id, \ + .owner = THIS_MODULE, \ + .min_uV = 700000, \ + .n_voltages = 128, \ + .uV_step = 7086, \ + .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \ + .vsel_mask = vmask, \ + .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \ + .enable_mask = emask, \ + .enable_time = etime, \ + .off_on_delay = odelay, \ + }, \ + .mode_mask = sleepmask, \ + } + +/* HI6421 BUCK3/4/5 share similar configurations as LDOs, with exception + * that it supports SLEEP mode, so has different .ops. + * + * _id - LDO id name string + * v_table - voltage table + * vreg - voltage select register + * vmask - voltage select mask + * ereg - enable register + * emask - enable mask + * odelay - off/on delay time in uS + * sleepmask - mask of sleep mode + */ +#define HI6421_BUCK345(_id, v_table, vreg, vmask, ereg, emask, \ + odelay, sleepmask) \ + [HI6421_##_id] = { \ + .desc = { \ + .name = #_id, \ + .ops = &hi6421_buck345_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = HI6421_##_id, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(v_table), \ + .volt_table = v_table, \ + .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \ + .vsel_mask = vmask, \ + .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \ + .enable_mask = emask, \ + .enable_time = HI6421_LDO_ENABLE_TIME, \ + .off_on_delay = odelay, \ + }, \ + .mode_mask = sleepmask, \ + } + +/* HI6421 regulator information */ +static struct hi6421_regulator_info + hi6421_regulator_info[HI6421_NUM_REGULATORS] = { + HI6421_LDO(LDO0, ldo_0_voltages, 0x20, 0x07, 0x20, 0x10, + 10000, 0x20, 8000), + HI6421_LDO_LINEAR(LDO1, 1700000, 4, 100000, 0x21, 0x03, 0x21, 0x10, + 10000, 0x20, 5000), + HI6421_LDO_LINEAR(LDO2, 1050000, 8, 50000, 0x22, 0x07, 0x22, 0x10, + 20000, 0x20, 8000), + HI6421_LDO_LINEAR(LDO3, 1050000, 8, 50000, 0x23, 0x07, 0x23, 0x10, + 20000, 0x20, 8000), + HI6421_LDO(LDO4, ldo_0_voltages, 0x24, 0x07, 0x24, 0x10, + 20000, 0x20, 8000), + HI6421_LDO(LDO5, ldo_0_voltages, 0x25, 0x07, 0x25, 0x10, + 20000, 0x20, 8000), + HI6421_LDO(LDO6, ldo_0_voltages, 0x26, 0x07, 0x26, 0x10, + 20000, 0x20, 8000), + HI6421_LDO(LDO7, ldo_0_voltages, 0x27, 0x07, 0x27, 0x10, + 20000, 0x20, 5000), + HI6421_LDO(LDO8, ldo_8_voltages, 0x28, 0x07, 0x28, 0x10, + 20000, 0x20, 8000), + HI6421_LDO(LDO9, ldo_0_voltages, 0x29, 0x07, 0x29, 0x10, + 40000, 0x20, 8000), + HI6421_LDO(LDO10, ldo_0_voltages, 0x2a, 0x07, 0x2a, 0x10, + 40000, 0x20, 8000), + HI6421_LDO(LDO11, ldo_0_voltages, 0x2b, 0x07, 0x2b, 0x10, + 40000, 0x20, 8000), + HI6421_LDO(LDO12, ldo_0_voltages, 0x2c, 0x07, 0x2c, 0x10, + 40000, 0x20, 8000), + HI6421_LDO(LDO13, ldo_0_voltages, 0x2d, 0x07, 0x2d, 0x10, + 40000, 0x20, 8000), + HI6421_LDO(LDO14, ldo_0_voltages, 0x2e, 0x07, 0x2e, 0x10, + 40000, 0x20, 8000), + HI6421_LDO(LDO15, ldo_8_voltages, 0x2f, 0x07, 0x2f, 0x10, + 40000, 0x20, 8000), + HI6421_LDO(LDO16, ldo_0_voltages, 0x30, 0x07, 0x30, 0x10, + 40000, 0x20, 8000), + HI6421_LDO(LDO17, ldo_0_voltages, 0x31, 0x07, 0x31, 0x10, + 40000, 0x20, 8000), + HI6421_LDO(LDO18, ldo_0_voltages, 0x32, 0x07, 0x32, 0x10, + 40000, 0x20, 8000), + HI6421_LDO(LDO19, ldo_0_voltages, 0x33, 0x07, 0x33, 0x10, + 40000, 0x20, 8000), + HI6421_LDO(LDO20, ldo_0_voltages, 0x34, 0x07, 0x34, 0x10, + 40000, 0x20, 8000), + HI6421_LDO_LINEAR_RANGE(LDOAUDIO, 8, ldo_audio_volt_range, 0x36, + 0x70, 0x36, 0x01, 40000, 0x02, 5000), + HI6421_BUCK012(BUCK0, 0x0d, 0x7f, 0x0c, 0x01, 0x10, 400, 20000), + HI6421_BUCK012(BUCK1, 0x0f, 0x7f, 0x0e, 0x01, 0x10, 400, 20000), + HI6421_BUCK012(BUCK2, 0x11, 0x7f, 0x10, 0x01, 0x10, 350, 100), + HI6421_BUCK345(BUCK3, buck_3_voltages, 0x13, 0x07, 0x12, 0x01, + 20000, 0x10), + HI6421_BUCK345(BUCK4, buck_4_voltages, 0x15, 0x07, 0x14, 0x01, + 20000, 0x10), + HI6421_BUCK345(BUCK5, buck_5_voltages, 0x17, 0x07, 0x16, 0x01, + 20000, 0x10), +}; + +static int hi6421_regulator_enable(struct regulator_dev *rdev) +{ + struct hi6421_regulator_pdata *pdata; + + pdata = dev_get_drvdata(rdev->dev.parent); + /* hi6421 spec requires regulator enablement must be serialized: + * - Because when BUCK, LDO switching from off to on, it will have + * a huge instantaneous current; so you can not turn on two or + * more LDO or BUCKs simultaneously, or it may burn the chip. + */ + mutex_lock(&pdata->lock); + + /* call regulator regmap helper */ + regulator_enable_regmap(rdev); + + mutex_unlock(&pdata->lock); + return 0; +} + +static unsigned int hi6421_regulator_ldo_get_mode(struct regulator_dev *rdev) +{ + struct hi6421_regulator_info *info = rdev_get_drvdata(rdev); + u32 reg_val; + + regmap_read(rdev->regmap, rdev->desc->enable_reg, ®_val); + if (reg_val & info->mode_mask) + return REGULATOR_MODE_IDLE; + + return REGULATOR_MODE_NORMAL; +} + +static unsigned int hi6421_regulator_buck_get_mode(struct regulator_dev *rdev) +{ + struct hi6421_regulator_info *info = rdev_get_drvdata(rdev); + u32 reg_val; + + regmap_read(rdev->regmap, rdev->desc->enable_reg, ®_val); + if (reg_val & info->mode_mask) + return REGULATOR_MODE_STANDBY; + + return REGULATOR_MODE_NORMAL; +} + +static int hi6421_regulator_ldo_set_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct hi6421_regulator_info *info = rdev_get_drvdata(rdev); + u32 new_mode; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + new_mode = 0; + break; + case REGULATOR_MODE_IDLE: + new_mode = info->mode_mask; + break; + default: + return -EINVAL; + } + + /* set mode */ + regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + info->mode_mask, new_mode); + + return 0; +} + +static int hi6421_regulator_buck_set_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct hi6421_regulator_info *info = rdev_get_drvdata(rdev); + u32 new_mode; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + new_mode = 0; + break; + case REGULATOR_MODE_STANDBY: + new_mode = info->mode_mask; + break; + default: + return -EINVAL; + } + + /* set mode */ + regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + info->mode_mask, new_mode); + + return 0; +} + +unsigned int hi6421_regulator_ldo_get_optimum_mode(struct regulator_dev *rdev, + int input_uV, int output_uV, int load_uA) +{ + struct hi6421_regulator_info *info = rdev_get_drvdata(rdev); + + if (load_uA > info->eco_microamp) + return REGULATOR_MODE_NORMAL; + + return REGULATOR_MODE_IDLE; +} + +static const struct regulator_ops hi6421_ldo_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = hi6421_regulator_enable, + .disable = regulator_disable_regmap, + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_ascend, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_mode = hi6421_regulator_ldo_get_mode, + .set_mode = hi6421_regulator_ldo_set_mode, + .get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode, +}; + +static const struct regulator_ops hi6421_ldo_linear_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = hi6421_regulator_enable, + .disable = regulator_disable_regmap, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_mode = hi6421_regulator_ldo_get_mode, + .set_mode = hi6421_regulator_ldo_set_mode, + .get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode, +}; + +static const struct regulator_ops hi6421_ldo_linear_range_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = hi6421_regulator_enable, + .disable = regulator_disable_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_mode = hi6421_regulator_ldo_get_mode, + .set_mode = hi6421_regulator_ldo_set_mode, + .get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode, +}; + +static const struct regulator_ops hi6421_buck012_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = hi6421_regulator_enable, + .disable = regulator_disable_regmap, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_mode = hi6421_regulator_buck_get_mode, + .set_mode = hi6421_regulator_buck_set_mode, +}; + +static const struct regulator_ops hi6421_buck345_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = hi6421_regulator_enable, + .disable = regulator_disable_regmap, + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_ascend, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_mode = hi6421_regulator_buck_get_mode, + .set_mode = hi6421_regulator_buck_set_mode, +}; + +static int hi6421_regulator_register(struct platform_device *pdev, + struct regmap *rmap, + struct regulator_init_data *init_data, + int id, struct device_node *np) +{ + struct hi6421_regulator_info *info = NULL; + struct regulator_config config = { }; + struct regulator_dev *rdev; + + /* assign per-regulator data */ + info = &hi6421_regulator_info[id]; + + config.dev = &pdev->dev; + config.init_data = init_data; + config.driver_data = info; + config.regmap = rmap; + config.of_node = np; + + /* register regulator with framework */ + rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register regulator %s\n", + info->desc.name); + return PTR_ERR(rdev); + } + + return 0; +} + +static int hi6421_regulator_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np; + struct hi6421_pmic *pmic; + struct hi6421_regulator_pdata *pdata; + int i, ret = 0; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + mutex_init(&pdata->lock); + platform_set_drvdata(pdev, pdata); + + np = of_get_child_by_name(dev->parent->of_node, "regulators"); + if (!np) + return -ENODEV; + + ret = of_regulator_match(dev, np, + hi6421_regulator_match, + ARRAY_SIZE(hi6421_regulator_match)); + of_node_put(np); + if (ret < 0) { + dev_err(dev, "Error parsing regulator init data: %d\n", ret); + return ret; + } + + pmic = dev_get_drvdata(dev->parent); + + for (i = 0; i < ARRAY_SIZE(hi6421_regulator_info); i++) { + ret = hi6421_regulator_register(pdev, pmic->regmap, + hi6421_regulator_match[i].init_data, i, + hi6421_regulator_match[i].of_node); + if (ret) + return ret; + } + + return 0; +} + +static struct platform_driver hi6421_regulator_driver = { + .driver = { + .name = "hi6421-regulator", + .owner = THIS_MODULE, + }, + .probe = hi6421_regulator_probe, +}; +module_platform_driver(hi6421_regulator_driver); + +MODULE_AUTHOR("Guodong Xu <guodong.xu@linaro.org>"); +MODULE_DESCRIPTION("Hi6421 regulator driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index 84bbda10c396..80ba2a35a04b 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h @@ -35,4 +35,18 @@ struct regulator { struct dentry *debugfs; }; +#ifdef CONFIG_OF +struct regulator_init_data *regulator_of_get_init_data(struct device *dev, + const struct regulator_desc *desc, + struct device_node **node); +#else +static inline struct regulator_init_data * +regulator_of_get_init_data(struct device *dev, + const struct regulator_desc *desc, + struct device_node **node) +{ + return NULL; +} +#endif + #endif diff --git a/drivers/regulator/isl9305.c b/drivers/regulator/isl9305.c new file mode 100644 index 000000000000..92fefd98da58 --- /dev/null +++ b/drivers/regulator/isl9305.c @@ -0,0 +1,207 @@ +/* + * isl9305 - Intersil ISL9305 DCDC regulator + * + * Copyright 2014 Linaro Ltd + * + * Author: Mark Brown <broonie@kernel.org> + * + * 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/module.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/of.h> +#include <linux/platform_data/isl9305.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/of_regulator.h> +#include <linux/slab.h> + +/* + * Registers + */ +#define ISL9305_DCD1OUT 0x0 +#define ISL9305_DCD2OUT 0x1 +#define ISL9305_LDO1OUT 0x2 +#define ISL9305_LDO2OUT 0x3 +#define ISL9305_DCD_PARAMETER 0x4 +#define ISL9305_SYSTEM_PARAMETER 0x5 +#define ISL9305_DCD_SRCTL 0x6 + +#define ISL9305_MAX_REG ISL9305_DCD_SRCTL + +/* + * DCD_PARAMETER + */ +#define ISL9305_DCD_PHASE 0x40 +#define ISL9305_DCD2_ULTRA 0x20 +#define ISL9305_DCD1_ULTRA 0x10 +#define ISL9305_DCD2_BLD 0x08 +#define ISL9305_DCD1_BLD 0x04 +#define ISL9305_DCD2_MODE 0x02 +#define ISL9305_DCD1_MODE 0x01 + +/* + * SYSTEM_PARAMETER + */ +#define ISL9305_I2C_EN 0x40 +#define ISL9305_DCDPOR_MASK 0x30 +#define ISL9305_LDO2_EN 0x08 +#define ISL9305_LDO1_EN 0x04 +#define ISL9305_DCD2_EN 0x02 +#define ISL9305_DCD1_EN 0x01 + +/* + * DCD_SRCTL + */ +#define ISL9305_DCD2SR_MASK 0xc0 +#define ISL9305_DCD1SR_MASK 0x07 + +static const struct regulator_ops isl9305_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +}; + +static const struct regulator_desc isl9305_regulators[] = { + [ISL9305_DCD1] = { + .name = "DCD1", + .of_match = of_match_ptr("dcd1"), + .regulators_node = of_match_ptr("regulators"), + .n_voltages = 0x70, + .min_uV = 825000, + .uV_step = 25000, + .vsel_reg = ISL9305_DCD1OUT, + .vsel_mask = 0x7f, + .enable_reg = ISL9305_SYSTEM_PARAMETER, + .enable_mask = ISL9305_DCD1_EN, + .supply_name = "VINDCD1", + .ops = &isl9305_ops, + }, + [ISL9305_DCD2] = { + .name = "DCD2", + .of_match = of_match_ptr("dcd2"), + .regulators_node = of_match_ptr("regulators"), + .n_voltages = 0x70, + .min_uV = 825000, + .uV_step = 25000, + .vsel_reg = ISL9305_DCD2OUT, + .vsel_mask = 0x7f, + .enable_reg = ISL9305_SYSTEM_PARAMETER, + .enable_mask = ISL9305_DCD2_EN, + .supply_name = "VINDCD2", + .ops = &isl9305_ops, + }, + [ISL9305_LDO1] = { + .name = "LDO1", + .of_match = of_match_ptr("ldo1"), + .regulators_node = of_match_ptr("regulators"), + .n_voltages = 0x37, + .min_uV = 900000, + .uV_step = 50000, + .vsel_reg = ISL9305_LDO1OUT, + .vsel_mask = 0x3f, + .enable_reg = ISL9305_SYSTEM_PARAMETER, + .enable_mask = ISL9305_LDO1_EN, + .supply_name = "VINLDO1", + .ops = &isl9305_ops, + }, + [ISL9305_LDO2] = { + .name = "LDO2", + .of_match = of_match_ptr("ldo2"), + .regulators_node = of_match_ptr("regulators"), + .n_voltages = 0x37, + .min_uV = 900000, + .uV_step = 50000, + .vsel_reg = ISL9305_LDO2OUT, + .vsel_mask = 0x3f, + .enable_reg = ISL9305_SYSTEM_PARAMETER, + .enable_mask = ISL9305_LDO2_EN, + .supply_name = "VINLDO2", + .ops = &isl9305_ops, + }, +}; + +static const struct regmap_config isl9305_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = ISL9305_MAX_REG, + .cache_type = REGCACHE_RBTREE, +}; + +static int isl9305_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regulator_config config = { }; + struct isl9305_pdata *pdata = i2c->dev.platform_data; + struct regulator_dev *rdev; + struct regmap *regmap; + int i, ret; + + regmap = devm_regmap_init_i2c(i2c, &isl9305_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); + return ret; + } + + config.dev = &i2c->dev; + + for (i = 0; i < ARRAY_SIZE(isl9305_regulators); i++) { + if (pdata) + config.init_data = pdata->init_data[i]; + else + config.init_data = NULL; + + rdev = devm_regulator_register(&i2c->dev, + &isl9305_regulators[i], + &config); + if (IS_ERR(rdev)) { + ret = PTR_ERR(rdev); + dev_err(&i2c->dev, "Failed to register %s: %d\n", + isl9305_regulators[i].name, ret); + return ret; + } + } + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id isl9305_dt_ids[] = { + { .compatible = "isl,isl9305" }, + { .compatible = "isl,isl9305h" }, + {}, +}; +#endif + +static const struct i2c_device_id isl9305_i2c_id[] = { + { "isl9305", }, + { "isl9305h", }, + { } +}; +MODULE_DEVICE_TABLE(i2c, isl9305_i2c_id); + +static struct i2c_driver isl9305_regulator_driver = { + .driver = { + .name = "isl9305", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(isl9305_dt_ids), + }, + .probe = isl9305_i2c_probe, + .id_table = isl9305_i2c_id, +}; + +module_i2c_driver(isl9305_regulator_driver); + +MODULE_AUTHOR("Mark Brown"); +MODULE_DESCRIPTION("Intersil ISL9305 DCDC regulator"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c index c756955bfcc5..0ce8e4e0fa73 100644 --- a/drivers/regulator/ltc3589.c +++ b/drivers/regulator/ltc3589.c @@ -372,6 +372,7 @@ static bool ltc3589_volatile_reg(struct device *dev, unsigned int reg) switch (reg) { case LTC3589_IRQSTAT: case LTC3589_PGSTAT: + case LTC3589_VCCR: return true; } return false; diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index d23d0577754b..86db310d5304 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -24,6 +24,8 @@ #include <linux/regulator/driver.h> #include <linux/slab.h> #include <linux/regulator/max1586.h> +#include <linux/of_device.h> +#include <linux/regulator/of_regulator.h> #define MAX1586_V3_MAX_VSEL 31 #define MAX1586_V6_MAX_VSEL 3 @@ -157,13 +159,87 @@ static struct regulator_desc max1586_reg[] = { }, }; +static int of_get_max1586_platform_data(struct device *dev, + struct max1586_platform_data *pdata) +{ + struct max1586_subdev_data *sub; + struct of_regulator_match rmatch[ARRAY_SIZE(max1586_reg)]; + struct device_node *np = dev->of_node; + int i, matched; + + if (of_property_read_u32(np, "v3-gain", + &pdata->v3_gain) < 0) { + dev_err(dev, "%s has no 'v3-gain' property\n", np->full_name); + return -EINVAL; + } + + np = of_get_child_by_name(np, "regulators"); + if (!np) { + dev_err(dev, "missing 'regulators' subnode in DT\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(rmatch); i++) + rmatch[i].name = max1586_reg[i].name; + + matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(rmatch)); + of_node_put(np); + /* + * If matched is 0, ie. neither Output_V3 nor Output_V6 have been found, + * return 0, which signals the normal situation where no subregulator is + * available. This is normal because the max1586 doesn't provide any + * readback support, so the subregulators can't report any status + * anyway. If matched < 0, return the error. + */ + if (matched <= 0) + return matched; + + pdata->subdevs = devm_kzalloc(dev, sizeof(struct max1586_subdev_data) * + matched, GFP_KERNEL); + if (!pdata->subdevs) + return -ENOMEM; + + pdata->num_subdevs = matched; + sub = pdata->subdevs; + + for (i = 0; i < matched; i++) { + sub->id = i; + sub->name = rmatch[i].of_node->name; + sub->platform_data = rmatch[i].init_data; + sub++; + } + + return 0; +} + +static const struct of_device_id max1586_of_match[] = { + { .compatible = "maxim,max1586", }, + {}, +}; +MODULE_DEVICE_TABLE(of, max1586_of_match); + static int max1586_pmic_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { - struct max1586_platform_data *pdata = dev_get_platdata(&client->dev); + struct max1586_platform_data *pdata, pdata_of; struct regulator_config config = { }; struct max1586_data *max1586; - int i, id; + int i, id, ret; + const struct of_device_id *match; + + pdata = dev_get_platdata(&client->dev); + if (client->dev.of_node && !pdata) { + match = of_match_device(of_match_ptr(max1586_of_match), + &client->dev); + if (!match) { + dev_err(&client->dev, "Error: No device match found\n"); + return -ENODEV; + } + ret = of_get_max1586_platform_data(&client->dev, &pdata_of); + if (ret < 0) + return ret; + pdata = &pdata_of; + } max1586 = devm_kzalloc(&client->dev, sizeof(struct max1586_data), GFP_KERNEL); @@ -229,6 +305,7 @@ static struct i2c_driver max1586_pmic_driver = { .driver = { .name = "max1586", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(max1586_of_match), }, .id_table = max1586_id, }; diff --git a/drivers/regulator/max77802.c b/drivers/regulator/max77802.c new file mode 100644 index 000000000000..d89792b084e9 --- /dev/null +++ b/drivers/regulator/max77802.c @@ -0,0 +1,586 @@ +/* + * max77802.c - Regulator driver for the Maxim 77802 + * + * Copyright (C) 2013-2014 Google, Inc + * Simon Glass <sjg@chromium.org> + * + * Copyright (C) 2012 Samsung Electronics + * Chiwoong Byun <woong.byun@smasung.com> + * Jonghwa Lee <jonghwa3.lee@samsung.com> + * + * 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. + * + * This program is distributed in the hope that 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. + * + * This driver is based on max8997.c + */ + +#include <linux/kernel.h> +#include <linux/bug.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/slab.h> +#include <linux/gpio/consumer.h> +#include <linux/platform_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/mfd/max77686.h> +#include <linux/mfd/max77686-private.h> + +/* Default ramp delay in case it is not manually set */ +#define MAX77802_RAMP_DELAY 100000 /* uV/us */ + +#define MAX77802_OPMODE_SHIFT_LDO 6 +#define MAX77802_OPMODE_BUCK234_SHIFT 4 +#define MAX77802_OPMODE_MASK 0x3 + +#define MAX77802_VSEL_MASK 0x3F +#define MAX77802_DVS_VSEL_MASK 0xFF + +#define MAX77802_RAMP_RATE_MASK_2BIT 0xC0 +#define MAX77802_RAMP_RATE_SHIFT_2BIT 6 +#define MAX77802_RAMP_RATE_MASK_4BIT 0xF0 +#define MAX77802_RAMP_RATE_SHIFT_4BIT 4 + +/* MAX77802 has two register formats: 2-bit and 4-bit */ +static const unsigned int ramp_table_77802_2bit[] = { + 12500, + 25000, + 50000, + 100000, +}; + +static unsigned int ramp_table_77802_4bit[] = { + 1000, 2000, 3030, 4000, + 5000, 5880, 7140, 8330, + 9090, 10000, 11110, 12500, + 16670, 25000, 50000, 100000, +}; + +struct max77802_regulator_prv { + unsigned int opmode[MAX77802_REG_MAX]; +}; + +static int max77802_get_opmode_shift(int id) +{ + if (id == MAX77802_BUCK1 || (id >= MAX77802_BUCK5 && + id <= MAX77802_BUCK10)) + return 0; + + if (id >= MAX77802_BUCK2 && id <= MAX77802_BUCK4) + return MAX77802_OPMODE_BUCK234_SHIFT; + + if (id >= MAX77802_LDO1 && id <= MAX77802_LDO35) + return MAX77802_OPMODE_SHIFT_LDO; + + return -EINVAL; +} + +/* + * Some BUCKS supports Normal[ON/OFF] mode during suspend + * + * BUCK 1, 6, 2-4, 5, 7-10 (all) + * + * The other mode (0x02) will make PWRREQ switch between normal + * and low power. + */ +static int max77802_buck_set_suspend_disable(struct regulator_dev *rdev) +{ + unsigned int val = MAX77802_OPMODE_STANDBY; + struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + int shift = max77802_get_opmode_shift(id); + + max77802->opmode[id] = val; + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, val << shift); +} + +/* + * Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state + * (Enable Control Logic1 by PWRREQ) + * + * LDOs 2, 4-19, 22-35. + * + */ +static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev, + unsigned int mode) +{ + struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + unsigned int val; + int shift = max77802_get_opmode_shift(id); + + switch (mode) { + case REGULATOR_MODE_IDLE: /* ON in LP Mode */ + val = MAX77802_OPMODE_LP; + break; + case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ + val = MAX77802_OPMODE_NORMAL; + break; + case REGULATOR_MODE_STANDBY: /* ON/OFF by PWRREQ */ + val = MAX77802_OPMODE_STANDBY; + break; + default: + dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", + rdev->desc->name, mode); + return -EINVAL; + } + + max77802->opmode[id] = val; + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, val << shift); +} + +/* + * Mode 1 (Output[ON/OFF] by PWRREQ) is not supported on some LDOs + * (Enable Control Logic2 by PWRREQ) + * + * LDOs 1, 20, 21, and 3, + * + */ +static int max77802_ldo_set_suspend_mode_logic2(struct regulator_dev *rdev, + unsigned int mode) +{ + struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + unsigned int val; + int shift = max77802_get_opmode_shift(id); + + switch (mode) { + case REGULATOR_MODE_IDLE: /* ON in LP Mode */ + val = MAX77802_OPMODE_LP; + break; + case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ + val = MAX77802_OPMODE_NORMAL; + break; + default: + dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", + rdev->desc->name, mode); + return -EINVAL; + } + + max77802->opmode[id] = val; + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, val << shift); +} + +static int max77802_enable(struct regulator_dev *rdev) +{ + struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + int shift = max77802_get_opmode_shift(id); + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, + max77802->opmode[id] << shift); +} + +static int max77802_find_ramp_value(struct regulator_dev *rdev, + const unsigned int limits[], int size, + unsigned int ramp_delay) +{ + int i; + + for (i = 0; i < size; i++) { + if (ramp_delay <= limits[i]) + return i; + } + + /* Use maximum value for no ramp control */ + dev_warn(&rdev->dev, "%s: ramp_delay: %d not supported, setting 100000\n", + rdev->desc->name, ramp_delay); + return size - 1; +} + +/* Used for BUCKs 2-4 */ +static int max77802_set_ramp_delay_2bit(struct regulator_dev *rdev, + int ramp_delay) +{ + int id = rdev_get_id(rdev); + unsigned int ramp_value; + + if (id > MAX77802_BUCK4) { + dev_warn(&rdev->dev, + "%s: regulator: ramp delay not supported\n", + rdev->desc->name); + return -EINVAL; + } + ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_2bit, + ARRAY_SIZE(ramp_table_77802_2bit), ramp_delay); + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + MAX77802_RAMP_RATE_MASK_2BIT, + ramp_value << MAX77802_RAMP_RATE_SHIFT_2BIT); +} + +/* For BUCK1, 6 */ +static int max77802_set_ramp_delay_4bit(struct regulator_dev *rdev, + int ramp_delay) +{ + unsigned int ramp_value; + + ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_4bit, + ARRAY_SIZE(ramp_table_77802_4bit), ramp_delay); + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + MAX77802_RAMP_RATE_MASK_4BIT, + ramp_value << MAX77802_RAMP_RATE_SHIFT_4BIT); +} + +/* + * LDOs 2, 4-19, 22-35 + */ +static struct regulator_ops max77802_ldo_ops_logic1 = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77802_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_suspend_mode = max77802_ldo_set_suspend_mode_logic1, +}; + +/* + * LDOs 1, 20, 21, 3 + */ +static struct regulator_ops max77802_ldo_ops_logic2 = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77802_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_suspend_mode = max77802_ldo_set_suspend_mode_logic2, +}; + +/* BUCKS 1, 6 */ +static struct regulator_ops max77802_buck_16_dvs_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77802_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = max77802_set_ramp_delay_4bit, + .set_suspend_disable = max77802_buck_set_suspend_disable, +}; + +/* BUCKs 2-4, 5, 7-10 */ +static struct regulator_ops max77802_buck_dvs_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77802_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = max77802_set_ramp_delay_2bit, + .set_suspend_disable = max77802_buck_set_suspend_disable, +}; + +/* LDOs 3-7, 9-14, 18-26, 28, 29, 32-34 */ +#define regulator_77802_desc_p_ldo(num, supply, log) { \ + .name = "LDO"#num, \ + .id = MAX77802_LDO##num, \ + .supply_name = "inl"#supply, \ + .ops = &max77802_ldo_ops_logic##log, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 800000, \ + .uV_step = 50000, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 1 << 6, \ + .vsel_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ + .vsel_mask = MAX77802_VSEL_MASK, \ + .enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ + .enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \ +} + +/* LDOs 1, 2, 8, 15, 17, 27, 30, 35 */ +#define regulator_77802_desc_n_ldo(num, supply, log) { \ + .name = "LDO"#num, \ + .id = MAX77802_LDO##num, \ + .supply_name = "inl"#supply, \ + .ops = &max77802_ldo_ops_logic##log, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 800000, \ + .uV_step = 25000, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 1 << 6, \ + .vsel_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ + .vsel_mask = MAX77802_VSEL_MASK, \ + .enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ + .enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \ +} + +/* BUCKs 1, 6 */ +#define regulator_77802_desc_16_buck(num) { \ + .name = "BUCK"#num, \ + .id = MAX77802_BUCK##num, \ + .supply_name = "inb"#num, \ + .ops = &max77802_buck_16_dvs_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 612500, \ + .uV_step = 6250, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 1 << 8, \ + .vsel_reg = MAX77802_REG_BUCK ## num ## DVS1, \ + .vsel_mask = MAX77802_DVS_VSEL_MASK, \ + .enable_reg = MAX77802_REG_BUCK ## num ## CTRL, \ + .enable_mask = MAX77802_OPMODE_MASK, \ +} + +/* BUCKS 2-4 */ +#define regulator_77802_desc_234_buck(num) { \ + .name = "BUCK"#num, \ + .id = MAX77802_BUCK##num, \ + .supply_name = "inb"#num, \ + .ops = &max77802_buck_dvs_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 600000, \ + .uV_step = 6250, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 0x91, \ + .vsel_reg = MAX77802_REG_BUCK ## num ## DVS1, \ + .vsel_mask = MAX77802_DVS_VSEL_MASK, \ + .enable_reg = MAX77802_REG_BUCK ## num ## CTRL1, \ + .enable_mask = MAX77802_OPMODE_MASK << \ + MAX77802_OPMODE_BUCK234_SHIFT, \ +} + +/* BUCK 5 */ +#define regulator_77802_desc_buck5(num) { \ + .name = "BUCK"#num, \ + .id = MAX77802_BUCK##num, \ + .supply_name = "inb"#num, \ + .ops = &max77802_buck_dvs_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 750000, \ + .uV_step = 50000, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 1 << 6, \ + .vsel_reg = MAX77802_REG_BUCK5OUT, \ + .vsel_mask = MAX77802_VSEL_MASK, \ + .enable_reg = MAX77802_REG_BUCK5CTRL, \ + .enable_mask = MAX77802_OPMODE_MASK, \ +} + +/* BUCKs 7-10 */ +#define regulator_77802_desc_buck7_10(num) { \ + .name = "BUCK"#num, \ + .id = MAX77802_BUCK##num, \ + .supply_name = "inb"#num, \ + .ops = &max77802_buck_dvs_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 750000, \ + .uV_step = 50000, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 1 << 6, \ + .vsel_reg = MAX77802_REG_BUCK7OUT + (num - 7) * 3, \ + .vsel_mask = MAX77802_VSEL_MASK, \ + .enable_reg = MAX77802_REG_BUCK7CTRL + (num - 7) * 3, \ + .enable_mask = MAX77802_OPMODE_MASK, \ +} + +static struct regulator_desc regulators[] = { + regulator_77802_desc_16_buck(1), + regulator_77802_desc_234_buck(2), + regulator_77802_desc_234_buck(3), + regulator_77802_desc_234_buck(4), + regulator_77802_desc_buck5(5), + regulator_77802_desc_16_buck(6), + regulator_77802_desc_buck7_10(7), + regulator_77802_desc_buck7_10(8), + regulator_77802_desc_buck7_10(9), + regulator_77802_desc_buck7_10(10), + regulator_77802_desc_n_ldo(1, 10, 2), + regulator_77802_desc_n_ldo(2, 10, 1), + regulator_77802_desc_p_ldo(3, 3, 2), + regulator_77802_desc_p_ldo(4, 6, 1), + regulator_77802_desc_p_ldo(5, 3, 1), + regulator_77802_desc_p_ldo(6, 3, 1), + regulator_77802_desc_p_ldo(7, 3, 1), + regulator_77802_desc_n_ldo(8, 1, 1), + regulator_77802_desc_p_ldo(9, 5, 1), + regulator_77802_desc_p_ldo(10, 4, 1), + regulator_77802_desc_p_ldo(11, 4, 1), + regulator_77802_desc_p_ldo(12, 9, 1), + regulator_77802_desc_p_ldo(13, 4, 1), + regulator_77802_desc_p_ldo(14, 4, 1), + regulator_77802_desc_n_ldo(15, 1, 1), + regulator_77802_desc_n_ldo(17, 2, 1), + regulator_77802_desc_p_ldo(18, 7, 1), + regulator_77802_desc_p_ldo(19, 5, 1), + regulator_77802_desc_p_ldo(20, 7, 2), + regulator_77802_desc_p_ldo(21, 6, 2), + regulator_77802_desc_p_ldo(23, 9, 1), + regulator_77802_desc_p_ldo(24, 6, 1), + regulator_77802_desc_p_ldo(25, 9, 1), + regulator_77802_desc_p_ldo(26, 9, 1), + regulator_77802_desc_n_ldo(27, 2, 1), + regulator_77802_desc_p_ldo(28, 7, 1), + regulator_77802_desc_p_ldo(29, 7, 1), + regulator_77802_desc_n_ldo(30, 2, 1), + regulator_77802_desc_p_ldo(32, 9, 1), + regulator_77802_desc_p_ldo(33, 6, 1), + regulator_77802_desc_p_ldo(34, 9, 1), + regulator_77802_desc_n_ldo(35, 2, 1), +}; + +#ifdef CONFIG_OF +static int max77802_pmic_dt_parse_pdata(struct platform_device *pdev, + struct max77686_platform_data *pdata) +{ + struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); + struct device_node *pmic_np, *regulators_np; + struct max77686_regulator_data *rdata; + struct of_regulator_match rmatch; + unsigned int i; + + pmic_np = iodev->dev->of_node; + regulators_np = of_get_child_by_name(pmic_np, "regulators"); + if (!regulators_np) { + dev_err(&pdev->dev, "could not find regulators sub-node\n"); + return -EINVAL; + } + + pdata->num_regulators = ARRAY_SIZE(regulators); + rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * + pdata->num_regulators, GFP_KERNEL); + if (!rdata) { + of_node_put(regulators_np); + return -ENOMEM; + } + + for (i = 0; i < pdata->num_regulators; i++) { + rmatch.name = regulators[i].name; + rmatch.init_data = NULL; + rmatch.of_node = NULL; + if (of_regulator_match(&pdev->dev, regulators_np, &rmatch, + 1) != 1) { + dev_warn(&pdev->dev, "No matching regulator for '%s'\n", + rmatch.name); + continue; + } + rdata[i].initdata = rmatch.init_data; + rdata[i].of_node = rmatch.of_node; + rdata[i].id = regulators[i].id; + } + + pdata->regulators = rdata; + of_node_put(regulators_np); + + return 0; +} +#else +static int max77802_pmic_dt_parse_pdata(struct platform_device *pdev, + struct max77686_platform_data *pdata) +{ + return 0; +} +#endif /* CONFIG_OF */ + +static int max77802_pmic_probe(struct platform_device *pdev) +{ + struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); + struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev); + struct max77802_regulator_prv *max77802; + int i, ret = 0, val; + struct regulator_config config = { }; + + /* This is allocated by the MFD driver */ + if (!pdata) { + dev_err(&pdev->dev, "no platform data found for regulator\n"); + return -ENODEV; + } + + max77802 = devm_kzalloc(&pdev->dev, + sizeof(struct max77802_regulator_prv), + GFP_KERNEL); + if (!max77802) + return -ENOMEM; + + if (iodev->dev->of_node) { + ret = max77802_pmic_dt_parse_pdata(pdev, pdata); + if (ret) + return ret; + } + + config.dev = iodev->dev; + config.regmap = iodev->regmap; + config.driver_data = max77802; + platform_set_drvdata(pdev, max77802); + + for (i = 0; i < MAX77802_REG_MAX; i++) { + struct regulator_dev *rdev; + int id = pdata->regulators[i].id; + int shift = max77802_get_opmode_shift(id); + + config.init_data = pdata->regulators[i].initdata; + config.of_node = pdata->regulators[i].of_node; + + ret = regmap_read(iodev->regmap, regulators[i].enable_reg, &val); + val = val >> shift & MAX77802_OPMODE_MASK; + + /* + * If the regulator is disabled and the system warm rebooted, + * the hardware reports OFF as the regulator operating mode. + * Default to operating mode NORMAL in that case. + */ + if (val == MAX77802_OPMODE_OFF) + max77802->opmode[id] = MAX77802_OPMODE_NORMAL; + else + max77802->opmode[id] = val; + + rdev = devm_regulator_register(&pdev->dev, + ®ulators[i], &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, + "regulator init failed for %d\n", i); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static const struct platform_device_id max77802_pmic_id[] = { + {"max77802-pmic", 0}, + { }, +}; +MODULE_DEVICE_TABLE(platform, max77802_pmic_id); + +static struct platform_driver max77802_pmic_driver = { + .driver = { + .name = "max77802-pmic", + .owner = THIS_MODULE, + }, + .probe = max77802_pmic_probe, + .id_table = max77802_pmic_id, +}; + +module_platform_driver(max77802_pmic_driver); + +MODULE_DESCRIPTION("MAXIM 77802 Regulator Driver"); +MODULE_AUTHOR("Simon Glass <sjg@chromium.org>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index f374fa57220f..793b662a1967 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -526,6 +526,7 @@ static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev) return REGULATOR_MODE_NORMAL; } +static struct regulator_ops mc13892_vcam_ops; static int mc13892_regulator_probe(struct platform_device *pdev) { @@ -582,10 +583,12 @@ static int mc13892_regulator_probe(struct platform_device *pdev) } mc13xxx_unlock(mc13892); - mc13892_regulators[MC13892_VCAM].desc.ops->set_mode - = mc13892_vcam_set_mode; - mc13892_regulators[MC13892_VCAM].desc.ops->get_mode - = mc13892_vcam_get_mode; + /* update mc13892_vcam ops */ + memcpy(&mc13892_vcam_ops, mc13892_regulators[MC13892_VCAM].desc.ops, + sizeof(struct regulator_ops)); + mc13892_vcam_ops.set_mode = mc13892_vcam_set_mode, + mc13892_vcam_ops.get_mode = mc13892_vcam_get_mode, + mc13892_regulators[MC13892_VCAM].desc.ops = &mc13892_vcam_ops; mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, ARRAY_SIZE(mc13892_regulators)); diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index ee5e67bc8d5b..7a51814abdc5 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -14,8 +14,11 @@ #include <linux/slab.h> #include <linux/of.h> #include <linux/regulator/machine.h> +#include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> +#include "internal.h" + static void of_get_regulation_constraints(struct device_node *np, struct regulator_init_data **init_data) { @@ -189,3 +192,51 @@ int of_regulator_match(struct device *dev, struct device_node *node, return count; } EXPORT_SYMBOL_GPL(of_regulator_match); + +struct regulator_init_data *regulator_of_get_init_data(struct device *dev, + const struct regulator_desc *desc, + struct device_node **node) +{ + struct device_node *search, *child; + struct regulator_init_data *init_data = NULL; + const char *name; + + if (!dev->of_node || !desc->of_match) + return NULL; + + if (desc->regulators_node) + search = of_get_child_by_name(dev->of_node, + desc->regulators_node); + else + search = dev->of_node; + + if (!search) { + dev_err(dev, "Failed to find regulator container node\n"); + return NULL; + } + + for_each_child_of_node(search, child) { + name = of_get_property(child, "regulator-compatible", NULL); + if (!name) + name = child->name; + + if (strcmp(desc->of_match, name)) + continue; + + init_data = of_get_regulator_init_data(dev, child); + if (!init_data) { + dev_err(dev, + "failed to parse DT for regulator %s\n", + child->name); + break; + } + + of_node_get(child); + *node = child; + break; + } + + of_node_put(search); + + return init_data; +} diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c new file mode 100644 index 000000000000..d3f55eaea058 --- /dev/null +++ b/drivers/regulator/pwm-regulator.c @@ -0,0 +1,197 @@ +/* + * Regulator driver for PWM Regulators + * + * Copyright (C) 2014 - STMicroelectronics Inc. + * + * Author: Lee Jones <lee.jones@linaro.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/pwm.h> + +struct pwm_regulator_data { + struct regulator_desc desc; + struct pwm_voltages *duty_cycle_table; + struct pwm_device *pwm; + bool enabled; + int state; +}; + +struct pwm_voltages { + unsigned int uV; + unsigned int dutycycle; +}; + +static int pwm_regulator_get_voltage_sel(struct regulator_dev *dev) +{ + struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); + + return drvdata->state; +} + +static int pwm_regulator_set_voltage_sel(struct regulator_dev *dev, + unsigned selector) +{ + struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); + unsigned int pwm_reg_period; + int dutycycle; + int ret; + + pwm_reg_period = pwm_get_period(drvdata->pwm); + + dutycycle = (pwm_reg_period * + drvdata->duty_cycle_table[selector].dutycycle) / 100; + + ret = pwm_config(drvdata->pwm, dutycycle, pwm_reg_period); + if (ret) { + dev_err(&dev->dev, "Failed to configure PWM\n"); + return ret; + } + + drvdata->state = selector; + + if (!drvdata->enabled) { + ret = pwm_enable(drvdata->pwm); + if (ret) { + dev_err(&dev->dev, "Failed to enable PWM\n"); + return ret; + } + drvdata->enabled = true; + } + + return 0; +} + +static int pwm_regulator_list_voltage(struct regulator_dev *dev, + unsigned selector) +{ + struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); + + if (selector >= drvdata->desc.n_voltages) + return -EINVAL; + + return drvdata->duty_cycle_table[selector].uV; +} + +static struct regulator_ops pwm_regulator_voltage_ops = { + .set_voltage_sel = pwm_regulator_set_voltage_sel, + .get_voltage_sel = pwm_regulator_get_voltage_sel, + .list_voltage = pwm_regulator_list_voltage, + .map_voltage = regulator_map_voltage_iterate, +}; + +static const struct regulator_desc pwm_regulator_desc = { + .name = "pwm-regulator", + .ops = &pwm_regulator_voltage_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .supply_name = "pwm", +}; + +static int pwm_regulator_probe(struct platform_device *pdev) +{ + struct pwm_regulator_data *drvdata; + struct property *prop; + struct regulator_dev *regulator; + struct regulator_config config = { }; + struct device_node *np = pdev->dev.of_node; + int length, ret; + + if (!np) { + dev_err(&pdev->dev, "Device Tree node missing\n"); + return -EINVAL; + } + + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(pwm_regulator_desc)); + + /* determine the number of voltage-table */ + prop = of_find_property(np, "voltage-table", &length); + if (!prop) { + dev_err(&pdev->dev, "No voltage-table\n"); + return -EINVAL; + } + + if ((length < sizeof(*drvdata->duty_cycle_table)) || + (length % sizeof(*drvdata->duty_cycle_table))) { + dev_err(&pdev->dev, "voltage-table length(%d) is invalid\n", + length); + return -EINVAL; + } + + drvdata->desc.n_voltages = length / sizeof(*drvdata->duty_cycle_table); + + drvdata->duty_cycle_table = devm_kzalloc(&pdev->dev, + length, GFP_KERNEL); + if (!drvdata->duty_cycle_table) + return -ENOMEM; + + /* read voltage table from DT property */ + ret = of_property_read_u32_array(np, "voltage-table", + (u32 *)drvdata->duty_cycle_table, + length / sizeof(u32)); + if (ret < 0) { + dev_err(&pdev->dev, "read voltage-table failed\n"); + return ret; + } + + config.init_data = of_get_regulator_init_data(&pdev->dev, np); + if (!config.init_data) + return -ENOMEM; + + config.of_node = np; + config.dev = &pdev->dev; + config.driver_data = drvdata; + + drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); + if (IS_ERR(drvdata->pwm)) { + dev_err(&pdev->dev, "Failed to get PWM\n"); + return PTR_ERR(drvdata->pwm); + } + + regulator = devm_regulator_register(&pdev->dev, + &drvdata->desc, &config); + if (IS_ERR(regulator)) { + dev_err(&pdev->dev, "Failed to register regulator %s\n", + drvdata->desc.name); + return PTR_ERR(regulator); + } + + return 0; +} + +static const struct of_device_id pwm_of_match[] = { + { .compatible = "pwm-regulator" }, + { }, +}; +MODULE_DEVICE_TABLE(of, pwm_of_match); + +static struct platform_driver pwm_regulator_driver = { + .driver = { + .name = "pwm-regulator", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(pwm_of_match), + }, + .probe = pwm_regulator_probe, +}; + +module_platform_driver(pwm_regulator_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); +MODULE_DESCRIPTION("PWM Regulator Driver"); +MODULE_ALIAS("platform:pwm-regulator"); diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c new file mode 100644 index 000000000000..b55cd5b50ebe --- /dev/null +++ b/drivers/regulator/qcom_rpm-regulator.c @@ -0,0 +1,798 @@ +/* + * Copyright (c) 2014, Sony Mobile Communications AB. + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that 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. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/mfd/qcom_rpm.h> + +#include <dt-bindings/mfd/qcom-rpm.h> + +#define MAX_REQUEST_LEN 2 + +struct request_member { + int word; + unsigned int mask; + int shift; +}; + +struct rpm_reg_parts { + struct request_member mV; /* used if voltage is in mV */ + struct request_member uV; /* used if voltage is in uV */ + struct request_member ip; /* peak current in mA */ + struct request_member pd; /* pull down enable */ + struct request_member ia; /* average current in mA */ + struct request_member fm; /* force mode */ + struct request_member pm; /* power mode */ + struct request_member pc; /* pin control */ + struct request_member pf; /* pin function */ + struct request_member enable_state; /* NCP and switch */ + struct request_member comp_mode; /* NCP */ + struct request_member freq; /* frequency: NCP and SMPS */ + struct request_member freq_clk_src; /* clock source: SMPS */ + struct request_member hpm; /* switch: control OCP and SS */ + int request_len; +}; + +#define FORCE_MODE_IS_2_BITS(reg) \ + (((reg)->parts->fm.mask >> (reg)->parts->fm.shift) == 3) + +struct qcom_rpm_reg { + struct qcom_rpm *rpm; + + struct mutex lock; + struct device *dev; + struct regulator_desc desc; + const struct rpm_reg_parts *parts; + + int resource; + u32 val[MAX_REQUEST_LEN]; + + int uV; + int is_enabled; + + bool supports_force_mode_auto; + bool supports_force_mode_bypass; +}; + +static const struct rpm_reg_parts rpm8660_ldo_parts = { + .request_len = 2, + .mV = { 0, 0x00000FFF, 0 }, + .ip = { 0, 0x00FFF000, 12 }, + .fm = { 0, 0x03000000, 24 }, + .pc = { 0, 0x3C000000, 26 }, + .pf = { 0, 0xC0000000, 30 }, + .pd = { 1, 0x00000001, 0 }, + .ia = { 1, 0x00001FFE, 1 }, +}; + +static const struct rpm_reg_parts rpm8660_smps_parts = { + .request_len = 2, + .mV = { 0, 0x00000FFF, 0 }, + .ip = { 0, 0x00FFF000, 12 }, + .fm = { 0, 0x03000000, 24 }, + .pc = { 0, 0x3C000000, 26 }, + .pf = { 0, 0xC0000000, 30 }, + .pd = { 1, 0x00000001, 0 }, + .ia = { 1, 0x00001FFE, 1 }, + .freq = { 1, 0x001FE000, 13 }, + .freq_clk_src = { 1, 0x00600000, 21 }, +}; + +static const struct rpm_reg_parts rpm8660_switch_parts = { + .request_len = 1, + .enable_state = { 0, 0x00000001, 0 }, + .pd = { 0, 0x00000002, 1 }, + .pc = { 0, 0x0000003C, 2 }, + .pf = { 0, 0x000000C0, 6 }, + .hpm = { 0, 0x00000300, 8 }, +}; + +static const struct rpm_reg_parts rpm8660_ncp_parts = { + .request_len = 1, + .mV = { 0, 0x00000FFF, 0 }, + .enable_state = { 0, 0x00001000, 12 }, + .comp_mode = { 0, 0x00002000, 13 }, + .freq = { 0, 0x003FC000, 14 }, +}; + +static const struct rpm_reg_parts rpm8960_ldo_parts = { + .request_len = 2, + .uV = { 0, 0x007FFFFF, 0 }, + .pd = { 0, 0x00800000, 23 }, + .pc = { 0, 0x0F000000, 24 }, + .pf = { 0, 0xF0000000, 28 }, + .ip = { 1, 0x000003FF, 0 }, + .ia = { 1, 0x000FFC00, 10 }, + .fm = { 1, 0x00700000, 20 }, +}; + +static const struct rpm_reg_parts rpm8960_smps_parts = { + .request_len = 2, + .uV = { 0, 0x007FFFFF, 0 }, + .pd = { 0, 0x00800000, 23 }, + .pc = { 0, 0x0F000000, 24 }, + .pf = { 0, 0xF0000000, 28 }, + .ip = { 1, 0x000003FF, 0 }, + .ia = { 1, 0x000FFC00, 10 }, + .fm = { 1, 0x00700000, 20 }, + .pm = { 1, 0x00800000, 23 }, + .freq = { 1, 0x1F000000, 24 }, + .freq_clk_src = { 1, 0x60000000, 29 }, +}; + +static const struct rpm_reg_parts rpm8960_switch_parts = { + .request_len = 1, + .enable_state = { 0, 0x00000001, 0 }, + .pd = { 0, 0x00000002, 1 }, + .pc = { 0, 0x0000003C, 2 }, + .pf = { 0, 0x000003C0, 6 }, + .hpm = { 0, 0x00000C00, 10 }, +}; + +static const struct rpm_reg_parts rpm8960_ncp_parts = { + .request_len = 1, + .uV = { 0, 0x007FFFFF, 0 }, + .enable_state = { 0, 0x00800000, 23 }, + .comp_mode = { 0, 0x01000000, 24 }, + .freq = { 0, 0x3E000000, 25 }, +}; + +/* + * Physically available PMIC regulator voltage ranges + */ +static const struct regulator_linear_range pldo_ranges[] = { + REGULATOR_LINEAR_RANGE( 750000, 0, 59, 12500), + REGULATOR_LINEAR_RANGE(1500000, 60, 123, 25000), + REGULATOR_LINEAR_RANGE(3100000, 124, 160, 50000), +}; + +static const struct regulator_linear_range nldo_ranges[] = { + REGULATOR_LINEAR_RANGE( 750000, 0, 63, 12500), +}; + +static const struct regulator_linear_range nldo1200_ranges[] = { + REGULATOR_LINEAR_RANGE( 375000, 0, 59, 6250), + REGULATOR_LINEAR_RANGE( 750000, 60, 123, 12500), +}; + +static const struct regulator_linear_range smps_ranges[] = { + REGULATOR_LINEAR_RANGE( 375000, 0, 29, 12500), + REGULATOR_LINEAR_RANGE( 750000, 30, 89, 12500), + REGULATOR_LINEAR_RANGE(1500000, 90, 153, 25000), +}; + +static const struct regulator_linear_range ftsmps_ranges[] = { + REGULATOR_LINEAR_RANGE( 350000, 0, 6, 50000), + REGULATOR_LINEAR_RANGE( 700000, 7, 63, 12500), + REGULATOR_LINEAR_RANGE(1500000, 64, 100, 50000), +}; + +static const struct regulator_linear_range ncp_ranges[] = { + REGULATOR_LINEAR_RANGE(1500000, 0, 31, 50000), +}; + +static int rpm_reg_write(struct qcom_rpm_reg *vreg, + const struct request_member *req, + const int value) +{ + if (WARN_ON((value << req->shift) & ~req->mask)) + return -EINVAL; + + vreg->val[req->word] &= ~req->mask; + vreg->val[req->word] |= value << req->shift; + + return qcom_rpm_write(vreg->rpm, + vreg->resource, + vreg->val, + vreg->parts->request_len); +} + +static int rpm_reg_set_mV_sel(struct regulator_dev *rdev, + unsigned selector) +{ + struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); + const struct rpm_reg_parts *parts = vreg->parts; + const struct request_member *req = &parts->mV; + int ret = 0; + int uV; + + if (req->mask == 0) + return -EINVAL; + + uV = regulator_list_voltage_linear_range(rdev, selector); + if (uV < 0) + return uV; + + mutex_lock(&vreg->lock); + vreg->uV = uV; + if (vreg->is_enabled) + ret = rpm_reg_write(vreg, req, vreg->uV / 1000); + mutex_unlock(&vreg->lock); + + return ret; +} + +static int rpm_reg_set_uV_sel(struct regulator_dev *rdev, + unsigned selector) +{ + struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); + const struct rpm_reg_parts *parts = vreg->parts; + const struct request_member *req = &parts->uV; + int ret = 0; + int uV; + + if (req->mask == 0) + return -EINVAL; + + uV = regulator_list_voltage_linear_range(rdev, selector); + if (uV < 0) + return uV; + + mutex_lock(&vreg->lock); + vreg->uV = uV; + if (vreg->is_enabled) + ret = rpm_reg_write(vreg, req, vreg->uV); + mutex_unlock(&vreg->lock); + + return ret; +} + +static int rpm_reg_get_voltage(struct regulator_dev *rdev) +{ + struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); + + return vreg->uV; +} + +static int rpm_reg_mV_enable(struct regulator_dev *rdev) +{ + struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); + const struct rpm_reg_parts *parts = vreg->parts; + const struct request_member *req = &parts->mV; + int ret; + + if (req->mask == 0) + return -EINVAL; + + mutex_lock(&vreg->lock); + ret = rpm_reg_write(vreg, req, vreg->uV / 1000); + if (!ret) + vreg->is_enabled = 1; + mutex_unlock(&vreg->lock); + + return ret; +} + +static int rpm_reg_uV_enable(struct regulator_dev *rdev) +{ + struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); + const struct rpm_reg_parts *parts = vreg->parts; + const struct request_member *req = &parts->uV; + int ret; + + if (req->mask == 0) + return -EINVAL; + + mutex_lock(&vreg->lock); + ret = rpm_reg_write(vreg, req, vreg->uV); + if (!ret) + vreg->is_enabled = 1; + mutex_unlock(&vreg->lock); + + return ret; +} + +static int rpm_reg_switch_enable(struct regulator_dev *rdev) +{ + struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); + const struct rpm_reg_parts *parts = vreg->parts; + const struct request_member *req = &parts->enable_state; + int ret; + + if (req->mask == 0) + return -EINVAL; + + mutex_lock(&vreg->lock); + ret = rpm_reg_write(vreg, req, 1); + if (!ret) + vreg->is_enabled = 1; + mutex_unlock(&vreg->lock); + + return ret; +} + +static int rpm_reg_mV_disable(struct regulator_dev *rdev) +{ + struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); + const struct rpm_reg_parts *parts = vreg->parts; + const struct request_member *req = &parts->mV; + int ret; + + if (req->mask == 0) + return -EINVAL; + + mutex_lock(&vreg->lock); + ret = rpm_reg_write(vreg, req, 0); + if (!ret) + vreg->is_enabled = 0; + mutex_unlock(&vreg->lock); + + return ret; +} + +static int rpm_reg_uV_disable(struct regulator_dev *rdev) +{ + struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); + const struct rpm_reg_parts *parts = vreg->parts; + const struct request_member *req = &parts->uV; + int ret; + + if (req->mask == 0) + return -EINVAL; + + mutex_lock(&vreg->lock); + ret = rpm_reg_write(vreg, req, 0); + if (!ret) + vreg->is_enabled = 0; + mutex_unlock(&vreg->lock); + + return ret; +} + +static int rpm_reg_switch_disable(struct regulator_dev *rdev) +{ + struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); + const struct rpm_reg_parts *parts = vreg->parts; + const struct request_member *req = &parts->enable_state; + int ret; + + if (req->mask == 0) + return -EINVAL; + + mutex_lock(&vreg->lock); + ret = rpm_reg_write(vreg, req, 0); + if (!ret) + vreg->is_enabled = 0; + mutex_unlock(&vreg->lock); + + return ret; +} + +static int rpm_reg_is_enabled(struct regulator_dev *rdev) +{ + struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); + + return vreg->is_enabled; +} + +static struct regulator_ops uV_ops = { + .list_voltage = regulator_list_voltage_linear_range, + + .set_voltage_sel = rpm_reg_set_uV_sel, + .get_voltage = rpm_reg_get_voltage, + + .enable = rpm_reg_uV_enable, + .disable = rpm_reg_uV_disable, + .is_enabled = rpm_reg_is_enabled, +}; + +static struct regulator_ops mV_ops = { + .list_voltage = regulator_list_voltage_linear_range, + + .set_voltage_sel = rpm_reg_set_mV_sel, + .get_voltage = rpm_reg_get_voltage, + + .enable = rpm_reg_mV_enable, + .disable = rpm_reg_mV_disable, + .is_enabled = rpm_reg_is_enabled, +}; + +static struct regulator_ops switch_ops = { + .enable = rpm_reg_switch_enable, + .disable = rpm_reg_switch_disable, + .is_enabled = rpm_reg_is_enabled, +}; + +/* + * PM8058 regulators + */ +static const struct qcom_rpm_reg pm8058_pldo = { + .desc.linear_ranges = pldo_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges), + .desc.n_voltages = 161, + .desc.ops = &mV_ops, + .parts = &rpm8660_ldo_parts, + .supports_force_mode_auto = false, + .supports_force_mode_bypass = false, +}; + +static const struct qcom_rpm_reg pm8058_nldo = { + .desc.linear_ranges = nldo_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges), + .desc.n_voltages = 64, + .desc.ops = &mV_ops, + .parts = &rpm8660_ldo_parts, + .supports_force_mode_auto = false, + .supports_force_mode_bypass = false, +}; + +static const struct qcom_rpm_reg pm8058_smps = { + .desc.linear_ranges = smps_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(smps_ranges), + .desc.n_voltages = 154, + .desc.ops = &mV_ops, + .parts = &rpm8660_smps_parts, + .supports_force_mode_auto = false, + .supports_force_mode_bypass = false, +}; + +static const struct qcom_rpm_reg pm8058_ncp = { + .desc.linear_ranges = ncp_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(ncp_ranges), + .desc.n_voltages = 32, + .desc.ops = &mV_ops, + .parts = &rpm8660_ncp_parts, +}; + +static const struct qcom_rpm_reg pm8058_switch = { + .desc.ops = &switch_ops, + .parts = &rpm8660_switch_parts, +}; + +/* + * PM8901 regulators + */ +static const struct qcom_rpm_reg pm8901_pldo = { + .desc.linear_ranges = pldo_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges), + .desc.n_voltages = 161, + .desc.ops = &mV_ops, + .parts = &rpm8660_ldo_parts, + .supports_force_mode_auto = false, + .supports_force_mode_bypass = true, +}; + +static const struct qcom_rpm_reg pm8901_nldo = { + .desc.linear_ranges = nldo_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges), + .desc.n_voltages = 64, + .desc.ops = &mV_ops, + .parts = &rpm8660_ldo_parts, + .supports_force_mode_auto = false, + .supports_force_mode_bypass = true, +}; + +static const struct qcom_rpm_reg pm8901_ftsmps = { + .desc.linear_ranges = ftsmps_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(ftsmps_ranges), + .desc.n_voltages = 101, + .desc.ops = &mV_ops, + .parts = &rpm8660_smps_parts, + .supports_force_mode_auto = true, + .supports_force_mode_bypass = false, +}; + +static const struct qcom_rpm_reg pm8901_switch = { + .desc.ops = &switch_ops, + .parts = &rpm8660_switch_parts, +}; + +/* + * PM8921 regulators + */ +static const struct qcom_rpm_reg pm8921_pldo = { + .desc.linear_ranges = pldo_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges), + .desc.n_voltages = 161, + .desc.ops = &uV_ops, + .parts = &rpm8960_ldo_parts, + .supports_force_mode_auto = false, + .supports_force_mode_bypass = true, +}; + +static const struct qcom_rpm_reg pm8921_nldo = { + .desc.linear_ranges = nldo_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges), + .desc.n_voltages = 64, + .desc.ops = &uV_ops, + .parts = &rpm8960_ldo_parts, + .supports_force_mode_auto = false, + .supports_force_mode_bypass = true, +}; + +static const struct qcom_rpm_reg pm8921_nldo1200 = { + .desc.linear_ranges = nldo1200_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(nldo1200_ranges), + .desc.n_voltages = 124, + .desc.ops = &uV_ops, + .parts = &rpm8960_ldo_parts, + .supports_force_mode_auto = false, + .supports_force_mode_bypass = true, +}; + +static const struct qcom_rpm_reg pm8921_smps = { + .desc.linear_ranges = smps_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(smps_ranges), + .desc.n_voltages = 154, + .desc.ops = &uV_ops, + .parts = &rpm8960_smps_parts, + .supports_force_mode_auto = true, + .supports_force_mode_bypass = false, +}; + +static const struct qcom_rpm_reg pm8921_ftsmps = { + .desc.linear_ranges = ftsmps_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(ftsmps_ranges), + .desc.n_voltages = 101, + .desc.ops = &uV_ops, + .parts = &rpm8960_smps_parts, + .supports_force_mode_auto = true, + .supports_force_mode_bypass = false, +}; + +static const struct qcom_rpm_reg pm8921_ncp = { + .desc.linear_ranges = ncp_ranges, + .desc.n_linear_ranges = ARRAY_SIZE(ncp_ranges), + .desc.n_voltages = 32, + .desc.ops = &uV_ops, + .parts = &rpm8960_ncp_parts, +}; + +static const struct qcom_rpm_reg pm8921_switch = { + .desc.ops = &switch_ops, + .parts = &rpm8960_switch_parts, +}; + +static const struct of_device_id rpm_of_match[] = { + { .compatible = "qcom,rpm-pm8058-pldo", .data = &pm8058_pldo }, + { .compatible = "qcom,rpm-pm8058-nldo", .data = &pm8058_nldo }, + { .compatible = "qcom,rpm-pm8058-smps", .data = &pm8058_smps }, + { .compatible = "qcom,rpm-pm8058-ncp", .data = &pm8058_ncp }, + { .compatible = "qcom,rpm-pm8058-switch", .data = &pm8058_switch }, + + { .compatible = "qcom,rpm-pm8901-pldo", .data = &pm8901_pldo }, + { .compatible = "qcom,rpm-pm8901-nldo", .data = &pm8901_nldo }, + { .compatible = "qcom,rpm-pm8901-ftsmps", .data = &pm8901_ftsmps }, + { .compatible = "qcom,rpm-pm8901-switch", .data = &pm8901_switch }, + + { .compatible = "qcom,rpm-pm8921-pldo", .data = &pm8921_pldo }, + { .compatible = "qcom,rpm-pm8921-nldo", .data = &pm8921_nldo }, + { .compatible = "qcom,rpm-pm8921-nldo1200", .data = &pm8921_nldo1200 }, + { .compatible = "qcom,rpm-pm8921-smps", .data = &pm8921_smps }, + { .compatible = "qcom,rpm-pm8921-ftsmps", .data = &pm8921_ftsmps }, + { .compatible = "qcom,rpm-pm8921-ncp", .data = &pm8921_ncp }, + { .compatible = "qcom,rpm-pm8921-switch", .data = &pm8921_switch }, + { } +}; +MODULE_DEVICE_TABLE(of, rpm_of_match); + +static int rpm_reg_set(struct qcom_rpm_reg *vreg, + const struct request_member *req, + const int value) +{ + if (req->mask == 0 || (value << req->shift) & ~req->mask) + return -EINVAL; + + vreg->val[req->word] &= ~req->mask; + vreg->val[req->word] |= value << req->shift; + + return 0; +} + +static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg) +{ + static const int freq_table[] = { + 19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 2740000, + 2400000, 2130000, 1920000, 1750000, 1600000, 1480000, 1370000, + 1280000, 1200000, + + }; + const char *key; + u32 freq; + int ret; + int i; + + key = "qcom,switch-mode-frequency"; + ret = of_property_read_u32(dev->of_node, key, &freq); + if (ret) { + dev_err(dev, "regulator requires %s property\n", key); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(freq_table); i++) { + if (freq == freq_table[i]) { + rpm_reg_set(vreg, &vreg->parts->freq, i + 1); + return 0; + } + } + + dev_err(dev, "invalid frequency %d\n", freq); + return -EINVAL; +} + +static int rpm_reg_probe(struct platform_device *pdev) +{ + struct regulator_init_data *initdata; + const struct qcom_rpm_reg *template; + const struct of_device_id *match; + struct regulator_config config = { }; + struct regulator_dev *rdev; + struct qcom_rpm_reg *vreg; + const char *key; + u32 force_mode; + bool pwm; + u32 val; + int ret; + + match = of_match_device(rpm_of_match, &pdev->dev); + template = match->data; + + initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); + if (!initdata) + return -EINVAL; + + vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL); + if (!vreg) { + dev_err(&pdev->dev, "failed to allocate vreg\n"); + return -ENOMEM; + } + memcpy(vreg, template, sizeof(*vreg)); + mutex_init(&vreg->lock); + vreg->dev = &pdev->dev; + vreg->desc.id = -1; + vreg->desc.owner = THIS_MODULE; + vreg->desc.type = REGULATOR_VOLTAGE; + vreg->desc.name = pdev->dev.of_node->name; + + vreg->rpm = dev_get_drvdata(pdev->dev.parent); + if (!vreg->rpm) { + dev_err(&pdev->dev, "unable to retrieve handle to rpm\n"); + return -ENODEV; + } + + key = "reg"; + ret = of_property_read_u32(pdev->dev.of_node, key, &val); + if (ret) { + dev_err(&pdev->dev, "failed to read %s\n", key); + return ret; + } + vreg->resource = val; + + if ((vreg->parts->uV.mask || vreg->parts->mV.mask) && + (!initdata->constraints.min_uV || !initdata->constraints.max_uV)) { + dev_err(&pdev->dev, "no voltage specified for regulator\n"); + return -EINVAL; + } + + key = "bias-pull-down"; + if (of_property_read_bool(pdev->dev.of_node, key)) { + ret = rpm_reg_set(vreg, &vreg->parts->pd, 1); + if (ret) { + dev_err(&pdev->dev, "%s is invalid", key); + return ret; + } + } + + if (vreg->parts->freq.mask) { + ret = rpm_reg_of_parse_freq(&pdev->dev, vreg); + if (ret < 0) + return ret; + } + + if (vreg->parts->pm.mask) { + key = "qcom,power-mode-hysteretic"; + pwm = !of_property_read_bool(pdev->dev.of_node, key); + + ret = rpm_reg_set(vreg, &vreg->parts->pm, pwm); + if (ret) { + dev_err(&pdev->dev, "failed to set power mode\n"); + return ret; + } + } + + if (vreg->parts->fm.mask) { + force_mode = -1; + + key = "qcom,force-mode"; + ret = of_property_read_u32(pdev->dev.of_node, key, &val); + if (ret == -EINVAL) { + val = QCOM_RPM_FORCE_MODE_NONE; + } else if (ret < 0) { + dev_err(&pdev->dev, "failed to read %s\n", key); + return ret; + } + + /* + * If force-mode is encoded as 2 bits then the + * possible register values are: + * NONE, LPM, HPM + * otherwise: + * NONE, LPM, AUTO, HPM, BYPASS + */ + switch (val) { + case QCOM_RPM_FORCE_MODE_NONE: + force_mode = 0; + break; + case QCOM_RPM_FORCE_MODE_LPM: + force_mode = 1; + break; + case QCOM_RPM_FORCE_MODE_HPM: + if (FORCE_MODE_IS_2_BITS(vreg)) + force_mode = 2; + else + force_mode = 3; + break; + case QCOM_RPM_FORCE_MODE_AUTO: + if (vreg->supports_force_mode_auto) + force_mode = 2; + break; + case QCOM_RPM_FORCE_MODE_BYPASS: + if (vreg->supports_force_mode_bypass) + force_mode = 4; + break; + } + + if (force_mode < 0) { + dev_err(&pdev->dev, "invalid force mode\n"); + return -EINVAL; + } + + ret = rpm_reg_set(vreg, &vreg->parts->fm, force_mode); + if (ret) { + dev_err(&pdev->dev, "failed to set force mode\n"); + return ret; + } + } + + config.dev = &pdev->dev; + config.init_data = initdata; + config.driver_data = vreg; + config.of_node = pdev->dev.of_node; + rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "can't register regulator\n"); + return PTR_ERR(rdev); + } + + return 0; +} + +static struct platform_driver rpm_reg_driver = { + .probe = rpm_reg_probe, + .driver = { + .name = "qcom_rpm_reg", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rpm_of_match), + }, +}; + +static int __init rpm_reg_init(void) +{ + return platform_driver_register(&rpm_reg_driver); +} +subsys_initcall(rpm_reg_init); + +static void __exit rpm_reg_exit(void) +{ + platform_driver_unregister(&rpm_reg_driver); +} +module_exit(rpm_reg_exit) + +MODULE_DESCRIPTION("Qualcomm RPM regulator driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c new file mode 100644 index 000000000000..e305416d7697 --- /dev/null +++ b/drivers/regulator/rk808-regulator.c @@ -0,0 +1,381 @@ +/* + * Regulator driver for Rockchip RK808 + * + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: Chris Zhong <zyw@rock-chips.com> + * Author: Zhang Qing <zhangqing@rock-chips.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. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/mfd/rk808.h> +#include <linux/of_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/of_regulator.h> + +/* Field Definitions */ +#define RK808_BUCK_VSEL_MASK 0x3f +#define RK808_BUCK4_VSEL_MASK 0xf +#define RK808_LDO_VSEL_MASK 0x1f + +/* Ramp rate definitions for buck1 / buck2 only */ +#define RK808_RAMP_RATE_OFFSET 3 +#define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET) +#define RK808_RAMP_RATE_2MV_PER_US (0 << RK808_RAMP_RATE_OFFSET) +#define RK808_RAMP_RATE_4MV_PER_US (1 << RK808_RAMP_RATE_OFFSET) +#define RK808_RAMP_RATE_6MV_PER_US (2 << RK808_RAMP_RATE_OFFSET) +#define RK808_RAMP_RATE_10MV_PER_US (3 << RK808_RAMP_RATE_OFFSET) + +static const int rk808_buck_config_regs[] = { + RK808_BUCK1_CONFIG_REG, + RK808_BUCK2_CONFIG_REG, + RK808_BUCK3_CONFIG_REG, + RK808_BUCK4_CONFIG_REG, +}; + +static const struct regulator_linear_range rk808_buck_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(700000, 0, 63, 12500), +}; + +static const struct regulator_linear_range rk808_buck4_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0, 15, 100000), +}; + +static const struct regulator_linear_range rk808_ldo_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0, 16, 100000), +}; + +static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0, 13, 100000), + REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0), +}; + +static const struct regulator_linear_range rk808_ldo6_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0, 17, 100000), +}; + +static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + unsigned int ramp_value = RK808_RAMP_RATE_10MV_PER_US; + unsigned int reg = rk808_buck_config_regs[rdev->desc->id - + RK808_ID_DCDC1]; + + switch (ramp_delay) { + case 1 ... 2000: + ramp_value = RK808_RAMP_RATE_2MV_PER_US; + break; + case 2001 ... 4000: + ramp_value = RK808_RAMP_RATE_4MV_PER_US; + break; + case 4001 ... 6000: + ramp_value = RK808_RAMP_RATE_6MV_PER_US; + break; + case 6001 ... 10000: + break; + default: + pr_warn("%s ramp_delay: %d not supported, setting 10000\n", + rdev->desc->name, ramp_delay); + } + + return regmap_update_bits(rdev->regmap, reg, + RK808_RAMP_RATE_MASK, ramp_value); +} + +static struct regulator_ops rk808_buck1_2_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_ramp_delay = rk808_set_ramp_delay, +}; + +static struct regulator_ops rk808_reg_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static struct regulator_ops rk808_switch_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_desc rk808_reg[] = { + { + .name = "DCDC_REG1", + .supply_name = "vcc1", + .id = RK808_ID_DCDC1, + .ops = &rk808_buck1_2_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk808_buck_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_buck_voltage_ranges), + .vsel_reg = RK808_BUCK1_ON_VSEL_REG, + .vsel_mask = RK808_BUCK_VSEL_MASK, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(0), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG2", + .supply_name = "vcc2", + .id = RK808_ID_DCDC2, + .ops = &rk808_buck1_2_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk808_buck_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_buck_voltage_ranges), + .vsel_reg = RK808_BUCK2_ON_VSEL_REG, + .vsel_mask = RK808_BUCK_VSEL_MASK, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(1), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG3", + .supply_name = "vcc3", + .id = RK808_ID_DCDC3, + .ops = &rk808_switch_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 1, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(2), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG4", + .supply_name = "vcc4", + .id = RK808_ID_DCDC4, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 16, + .linear_ranges = rk808_buck4_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_buck4_voltage_ranges), + .vsel_reg = RK808_BUCK4_ON_VSEL_REG, + .vsel_mask = RK808_BUCK4_VSEL_MASK, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(3), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG1", + .supply_name = "vcc6", + .id = RK808_ID_LDO1, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk808_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), + .vsel_reg = RK808_LDO1_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(0), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG2", + .supply_name = "vcc6", + .id = RK808_ID_LDO2, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk808_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), + .vsel_reg = RK808_LDO2_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(1), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG3", + .supply_name = "vcc7", + .id = RK808_ID_LDO3, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 16, + .linear_ranges = rk808_ldo3_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo3_voltage_ranges), + .vsel_reg = RK808_LDO3_ON_VSEL_REG, + .vsel_mask = RK808_BUCK4_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(2), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG4", + .supply_name = "vcc9", + .id = RK808_ID_LDO4, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk808_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), + .vsel_reg = RK808_LDO4_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(3), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG5", + .supply_name = "vcc9", + .id = RK808_ID_LDO5, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk808_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), + .vsel_reg = RK808_LDO5_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(4), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG6", + .supply_name = "vcc10", + .id = RK808_ID_LDO6, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 18, + .linear_ranges = rk808_ldo6_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo6_voltage_ranges), + .vsel_reg = RK808_LDO6_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(5), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG7", + .supply_name = "vcc7", + .id = RK808_ID_LDO7, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 18, + .linear_ranges = rk808_ldo6_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo6_voltage_ranges), + .vsel_reg = RK808_LDO7_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(6), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG8", + .supply_name = "vcc11", + .id = RK808_ID_LDO8, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk808_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), + .vsel_reg = RK808_LDO8_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(7), + .owner = THIS_MODULE, + }, { + .name = "SWITCH_REG1", + .supply_name = "vcc8", + .id = RK808_ID_SWITCH1, + .ops = &rk808_switch_ops, + .type = REGULATOR_VOLTAGE, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(5), + .owner = THIS_MODULE, + }, { + .name = "SWITCH_REG2", + .supply_name = "vcc12", + .id = RK808_ID_SWITCH2, + .ops = &rk808_switch_ops, + .type = REGULATOR_VOLTAGE, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(6), + .owner = THIS_MODULE, + }, +}; + +static struct of_regulator_match rk808_reg_matches[] = { + [RK808_ID_DCDC1] = { .name = "DCDC_REG1" }, + [RK808_ID_DCDC2] = { .name = "DCDC_REG2" }, + [RK808_ID_DCDC3] = { .name = "DCDC_REG3" }, + [RK808_ID_DCDC4] = { .name = "DCDC_REG4" }, + [RK808_ID_LDO1] = { .name = "LDO_REG1" }, + [RK808_ID_LDO2] = { .name = "LDO_REG2" }, + [RK808_ID_LDO3] = { .name = "LDO_REG3" }, + [RK808_ID_LDO4] = { .name = "LDO_REG4" }, + [RK808_ID_LDO5] = { .name = "LDO_REG5" }, + [RK808_ID_LDO6] = { .name = "LDO_REG6" }, + [RK808_ID_LDO7] = { .name = "LDO_REG7" }, + [RK808_ID_LDO8] = { .name = "LDO_REG8" }, + [RK808_ID_SWITCH1] = { .name = "SWITCH_REG1" }, + [RK808_ID_SWITCH2] = { .name = "SWITCH_REG2" }, +}; + +static int rk808_regulator_probe(struct platform_device *pdev) +{ + struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); + struct i2c_client *client = rk808->i2c; + struct device_node *reg_np; + struct regulator_config config = {}; + struct regulator_dev *rk808_rdev; + int ret, i; + + reg_np = of_get_child_by_name(client->dev.of_node, "regulators"); + if (!reg_np) + return -ENXIO; + + ret = of_regulator_match(&pdev->dev, reg_np, rk808_reg_matches, + RK808_NUM_REGULATORS); + of_node_put(reg_np); + if (ret < 0) + return ret; + + /* Instantiate the regulators */ + for (i = 0; i < RK808_NUM_REGULATORS; i++) { + if (!rk808_reg_matches[i].init_data || + !rk808_reg_matches[i].of_node) + continue; + + config.dev = &client->dev; + config.driver_data = rk808; + config.regmap = rk808->regmap; + config.of_node = rk808_reg_matches[i].of_node; + config.init_data = rk808_reg_matches[i].init_data; + + rk808_rdev = devm_regulator_register(&pdev->dev, + &rk808_reg[i], &config); + if (IS_ERR(rk808_rdev)) { + dev_err(&client->dev, + "failed to register %d regulator\n", i); + return PTR_ERR(rk808_rdev); + } + } + + return 0; +} + +static struct platform_driver rk808_regulator_driver = { + .probe = rk808_regulator_probe, + .driver = { + .name = "rk808-regulator", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(rk808_regulator_driver); + +MODULE_DESCRIPTION("regulator driver for the rk808 series PMICs"); +MODULE_AUTHOR("Chris Zhong<zyw@rock-chips.com>"); +MODULE_AUTHOR("Zhang Qing<zhangqing@rock-chips.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rk808-regulator"); diff --git a/drivers/regulator/rn5t618-regulator.c b/drivers/regulator/rn5t618-regulator.c new file mode 100644 index 000000000000..e58d79aeb393 --- /dev/null +++ b/drivers/regulator/rn5t618-regulator.c @@ -0,0 +1,143 @@ +/* + * Regulator driver for Ricoh RN5T618 PMIC + * + * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/mfd/rn5t618.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/of_regulator.h> + +static struct regulator_ops rn5t618_reg_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear, +}; + +#define REG(rid, ereg, emask, vreg, vmask, min, max, step) \ + [RN5T618_##rid] = { \ + .name = #rid, \ + .id = RN5T618_##rid, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .ops = &rn5t618_reg_ops, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .min_uV = (min), \ + .uV_step = (step), \ + .enable_reg = RN5T618_##ereg, \ + .enable_mask = (emask), \ + .vsel_reg = RN5T618_##vreg, \ + .vsel_mask = (vmask), \ + } + +static struct regulator_desc rn5t618_regulators[] = { + /* DCDC */ + REG(DCDC1, DC1CTL, BIT(0), DC1DAC, 0xff, 600000, 3500000, 12500), + REG(DCDC2, DC2CTL, BIT(0), DC2DAC, 0xff, 600000, 3500000, 12500), + REG(DCDC3, DC3CTL, BIT(0), DC3DAC, 0xff, 600000, 3500000, 12500), + /* LDO */ + REG(LDO1, LDOEN1, BIT(0), LDO1DAC, 0x7f, 900000, 3500000, 25000), + REG(LDO2, LDOEN1, BIT(1), LDO2DAC, 0x7f, 900000, 3500000, 25000), + REG(LDO3, LDOEN1, BIT(2), LDO3DAC, 0x7f, 600000, 3500000, 25000), + REG(LDO4, LDOEN1, BIT(3), LDO4DAC, 0x7f, 900000, 3500000, 25000), + REG(LDO5, LDOEN1, BIT(4), LDO5DAC, 0x7f, 900000, 3500000, 25000), + /* LDO RTC */ + REG(LDORTC1, LDOEN2, BIT(4), LDORTCDAC, 0x7f, 1700000, 3500000, 25000), + REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000), +}; + +static struct of_regulator_match rn5t618_matches[] = { + [RN5T618_DCDC1] = { .name = "DCDC1" }, + [RN5T618_DCDC2] = { .name = "DCDC2" }, + [RN5T618_DCDC3] = { .name = "DCDC3" }, + [RN5T618_LDO1] = { .name = "LDO1" }, + [RN5T618_LDO2] = { .name = "LDO2" }, + [RN5T618_LDO3] = { .name = "LDO3" }, + [RN5T618_LDO4] = { .name = "LDO4" }, + [RN5T618_LDO5] = { .name = "LDO5" }, + [RN5T618_LDORTC1] = { .name = "LDORTC1" }, + [RN5T618_LDORTC2] = { .name = "LDORTC2" }, +}; + +static int rn5t618_regulator_parse_dt(struct platform_device *pdev) +{ + struct device_node *np, *regulators; + int ret; + + np = of_node_get(pdev->dev.parent->of_node); + if (!np) + return 0; + + regulators = of_get_child_by_name(np, "regulators"); + if (!regulators) { + dev_err(&pdev->dev, "regulators node not found\n"); + return -EINVAL; + } + + ret = of_regulator_match(&pdev->dev, regulators, rn5t618_matches, + ARRAY_SIZE(rn5t618_matches)); + of_node_put(regulators); + if (ret < 0) { + dev_err(&pdev->dev, "error parsing regulator init data: %d\n", + ret); + } + + return 0; +} + +static int rn5t618_regulator_probe(struct platform_device *pdev) +{ + struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = { }; + struct regulator_dev *rdev; + int ret, i; + + ret = rn5t618_regulator_parse_dt(pdev); + if (ret) + return ret; + + for (i = 0; i < RN5T618_REG_NUM; i++) { + config.dev = &pdev->dev; + config.init_data = rn5t618_matches[i].init_data; + config.of_node = rn5t618_matches[i].of_node; + config.regmap = rn5t618->regmap; + + rdev = devm_regulator_register(&pdev->dev, + &rn5t618_regulators[i], + &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register %s regulator\n", + rn5t618_regulators[i].name); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static struct platform_driver rn5t618_regulator_driver = { + .probe = rn5t618_regulator_probe, + .driver = { + .name = "rn5t618-regulator", + }, +}; + +module_platform_driver(rn5t618_regulator_driver); + +MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); +MODULE_DESCRIPTION("RN5T618 regulator driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c index ee83b4876420..4acefa6b462e 100644 --- a/drivers/regulator/s2mpa01.c +++ b/drivers/regulator/s2mpa01.c @@ -235,28 +235,14 @@ static struct regulator_ops s2mpa01_buck_ops = { .set_ramp_delay = s2mpa01_set_ramp_delay, }; -#define regulator_desc_ldo1(num) { \ +#define regulator_desc_ldo(num, step) { \ .name = "LDO"#num, \ .id = S2MPA01_LDO##num, \ .ops = &s2mpa01_ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = S2MPA01_LDO_MIN, \ - .uV_step = S2MPA01_LDO_STEP1, \ - .n_voltages = S2MPA01_LDO_N_VOLTAGES, \ - .vsel_reg = S2MPA01_REG_L1CTRL + num - 1, \ - .vsel_mask = S2MPA01_LDO_VSEL_MASK, \ - .enable_reg = S2MPA01_REG_L1CTRL + num - 1, \ - .enable_mask = S2MPA01_ENABLE_MASK \ -} -#define regulator_desc_ldo2(num) { \ - .name = "LDO"#num, \ - .id = S2MPA01_LDO##num, \ - .ops = &s2mpa01_ldo_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = S2MPA01_LDO_MIN, \ - .uV_step = S2MPA01_LDO_STEP2, \ + .min_uV = MIN_800_MV, \ + .uV_step = step, \ .n_voltages = S2MPA01_LDO_N_VOLTAGES, \ .vsel_reg = S2MPA01_REG_L1CTRL + num - 1, \ .vsel_mask = S2MPA01_LDO_VSEL_MASK, \ @@ -270,8 +256,8 @@ static struct regulator_ops s2mpa01_buck_ops = { .ops = &s2mpa01_buck_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = S2MPA01_BUCK_MIN1, \ - .uV_step = S2MPA01_BUCK_STEP1, \ + .min_uV = MIN_600_MV, \ + .uV_step = STEP_6_25_MV, \ .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ .ramp_delay = S2MPA01_RAMP_DELAY, \ .vsel_reg = S2MPA01_REG_B1CTRL2 + (num - 1) * 2, \ @@ -286,8 +272,8 @@ static struct regulator_ops s2mpa01_buck_ops = { .ops = &s2mpa01_buck_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = S2MPA01_BUCK_MIN2, \ - .uV_step = S2MPA01_BUCK_STEP1, \ + .min_uV = MIN_800_MV, \ + .uV_step = STEP_6_25_MV, \ .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ .ramp_delay = S2MPA01_RAMP_DELAY, \ .vsel_reg = S2MPA01_REG_B5CTRL2, \ @@ -296,14 +282,14 @@ static struct regulator_ops s2mpa01_buck_ops = { .enable_mask = S2MPA01_ENABLE_MASK \ } -#define regulator_desc_buck6_7(num) { \ +#define regulator_desc_buck6_10(num, min, step) { \ .name = "BUCK"#num, \ .id = S2MPA01_BUCK##num, \ .ops = &s2mpa01_buck_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = S2MPA01_BUCK_MIN1, \ - .uV_step = S2MPA01_BUCK_STEP1, \ + .min_uV = min, \ + .uV_step = step, \ .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ .ramp_delay = S2MPA01_RAMP_DELAY, \ .vsel_reg = S2MPA01_REG_B6CTRL2 + (num - 6) * 2, \ @@ -312,91 +298,43 @@ static struct regulator_ops s2mpa01_buck_ops = { .enable_mask = S2MPA01_ENABLE_MASK \ } -#define regulator_desc_buck8 { \ - .name = "BUCK8", \ - .id = S2MPA01_BUCK8, \ - .ops = &s2mpa01_buck_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = S2MPA01_BUCK_MIN2, \ - .uV_step = S2MPA01_BUCK_STEP2, \ - .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ - .ramp_delay = S2MPA01_RAMP_DELAY, \ - .vsel_reg = S2MPA01_REG_B8CTRL2, \ - .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ - .enable_reg = S2MPA01_REG_B8CTRL1, \ - .enable_mask = S2MPA01_ENABLE_MASK \ -} - -#define regulator_desc_buck9 { \ - .name = "BUCK9", \ - .id = S2MPA01_BUCK9, \ - .ops = &s2mpa01_buck_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = S2MPA01_BUCK_MIN4, \ - .uV_step = S2MPA01_BUCK_STEP2, \ - .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ - .ramp_delay = S2MPA01_RAMP_DELAY, \ - .vsel_reg = S2MPA01_REG_B9CTRL2, \ - .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ - .enable_reg = S2MPA01_REG_B9CTRL1, \ - .enable_mask = S2MPA01_ENABLE_MASK \ -} - -#define regulator_desc_buck10 { \ - .name = "BUCK10", \ - .id = S2MPA01_BUCK10, \ - .ops = &s2mpa01_buck_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = S2MPA01_BUCK_MIN3, \ - .uV_step = S2MPA01_BUCK_STEP2, \ - .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ - .ramp_delay = S2MPA01_RAMP_DELAY, \ - .vsel_reg = S2MPA01_REG_B10CTRL2, \ - .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ - .enable_reg = S2MPA01_REG_B10CTRL1, \ - .enable_mask = S2MPA01_ENABLE_MASK \ -} - static struct regulator_desc regulators[] = { - regulator_desc_ldo2(1), - regulator_desc_ldo1(2), - regulator_desc_ldo1(3), - regulator_desc_ldo1(4), - regulator_desc_ldo1(5), - regulator_desc_ldo2(6), - regulator_desc_ldo1(7), - regulator_desc_ldo1(8), - regulator_desc_ldo1(9), - regulator_desc_ldo1(10), - regulator_desc_ldo2(11), - regulator_desc_ldo1(12), - regulator_desc_ldo1(13), - regulator_desc_ldo1(14), - regulator_desc_ldo1(15), - regulator_desc_ldo1(16), - regulator_desc_ldo1(17), - regulator_desc_ldo1(18), - regulator_desc_ldo1(19), - regulator_desc_ldo1(20), - regulator_desc_ldo1(21), - regulator_desc_ldo2(22), - regulator_desc_ldo2(23), - regulator_desc_ldo1(24), - regulator_desc_ldo1(25), - regulator_desc_ldo1(26), + regulator_desc_ldo(1, STEP_25_MV), + regulator_desc_ldo(2, STEP_50_MV), + regulator_desc_ldo(3, STEP_50_MV), + regulator_desc_ldo(4, STEP_50_MV), + regulator_desc_ldo(5, STEP_50_MV), + regulator_desc_ldo(6, STEP_25_MV), + regulator_desc_ldo(7, STEP_50_MV), + regulator_desc_ldo(8, STEP_50_MV), + regulator_desc_ldo(9, STEP_50_MV), + regulator_desc_ldo(10, STEP_50_MV), + regulator_desc_ldo(11, STEP_25_MV), + regulator_desc_ldo(12, STEP_50_MV), + regulator_desc_ldo(13, STEP_50_MV), + regulator_desc_ldo(14, STEP_50_MV), + regulator_desc_ldo(15, STEP_50_MV), + regulator_desc_ldo(16, STEP_50_MV), + regulator_desc_ldo(17, STEP_50_MV), + regulator_desc_ldo(18, STEP_50_MV), + regulator_desc_ldo(19, STEP_50_MV), + regulator_desc_ldo(20, STEP_50_MV), + regulator_desc_ldo(21, STEP_50_MV), + regulator_desc_ldo(22, STEP_25_MV), + regulator_desc_ldo(23, STEP_25_MV), + regulator_desc_ldo(24, STEP_50_MV), + regulator_desc_ldo(25, STEP_50_MV), + regulator_desc_ldo(26, STEP_50_MV), regulator_desc_buck1_4(1), regulator_desc_buck1_4(2), regulator_desc_buck1_4(3), regulator_desc_buck1_4(4), regulator_desc_buck5, - regulator_desc_buck6_7(6), - regulator_desc_buck6_7(7), - regulator_desc_buck8, - regulator_desc_buck9, - regulator_desc_buck10, + regulator_desc_buck6_10(6, MIN_600_MV, STEP_6_25_MV), + regulator_desc_buck6_10(7, MIN_600_MV, STEP_6_25_MV), + regulator_desc_buck6_10(8, MIN_800_MV, STEP_12_5_MV), + regulator_desc_buck6_10(9, MIN_1500_MV, STEP_12_5_MV), + regulator_desc_buck6_10(10, MIN_1000_MV, STEP_12_5_MV), }; static int s2mpa01_pmic_probe(struct platform_device *pdev) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index b16c53a8272f..adab82d5279f 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -255,28 +255,14 @@ static struct regulator_ops s2mps11_buck_ops = { .set_ramp_delay = s2mps11_set_ramp_delay, }; -#define regulator_desc_s2mps11_ldo1(num) { \ +#define regulator_desc_s2mps11_ldo(num, step) { \ .name = "LDO"#num, \ .id = S2MPS11_LDO##num, \ .ops = &s2mps11_ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = S2MPS11_LDO_MIN, \ - .uV_step = S2MPS11_LDO_STEP1, \ - .n_voltages = S2MPS11_LDO_N_VOLTAGES, \ - .vsel_reg = S2MPS11_REG_L1CTRL + num - 1, \ - .vsel_mask = S2MPS11_LDO_VSEL_MASK, \ - .enable_reg = S2MPS11_REG_L1CTRL + num - 1, \ - .enable_mask = S2MPS11_ENABLE_MASK \ -} -#define regulator_desc_s2mps11_ldo2(num) { \ - .name = "LDO"#num, \ - .id = S2MPS11_LDO##num, \ - .ops = &s2mps11_ldo_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = S2MPS11_LDO_MIN, \ - .uV_step = S2MPS11_LDO_STEP2, \ + .min_uV = MIN_800_MV, \ + .uV_step = step, \ .n_voltages = S2MPS11_LDO_N_VOLTAGES, \ .vsel_reg = S2MPS11_REG_L1CTRL + num - 1, \ .vsel_mask = S2MPS11_LDO_VSEL_MASK, \ @@ -290,8 +276,8 @@ static struct regulator_ops s2mps11_buck_ops = { .ops = &s2mps11_buck_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = S2MPS11_BUCK_MIN1, \ - .uV_step = S2MPS11_BUCK_STEP1, \ + .min_uV = MIN_600_MV, \ + .uV_step = STEP_6_25_MV, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B1CTRL2 + (num - 1) * 2, \ @@ -306,8 +292,8 @@ static struct regulator_ops s2mps11_buck_ops = { .ops = &s2mps11_buck_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = S2MPS11_BUCK_MIN1, \ - .uV_step = S2MPS11_BUCK_STEP1, \ + .min_uV = MIN_600_MV, \ + .uV_step = STEP_6_25_MV, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B5CTRL2, \ @@ -316,14 +302,14 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -#define regulator_desc_s2mps11_buck6_8(num) { \ +#define regulator_desc_s2mps11_buck6_10(num, min, step) { \ .name = "BUCK"#num, \ .id = S2MPS11_BUCK##num, \ .ops = &s2mps11_buck_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = S2MPS11_BUCK_MIN1, \ - .uV_step = S2MPS11_BUCK_STEP1, \ + .min_uV = min, \ + .uV_step = step, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B6CTRL2 + (num - 6) * 2, \ @@ -332,87 +318,55 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -#define regulator_desc_s2mps11_buck9 { \ - .name = "BUCK9", \ - .id = S2MPS11_BUCK9, \ - .ops = &s2mps11_buck_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = S2MPS11_BUCK_MIN3, \ - .uV_step = S2MPS11_BUCK_STEP3, \ - .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ - .ramp_delay = S2MPS11_RAMP_DELAY, \ - .vsel_reg = S2MPS11_REG_B9CTRL2, \ - .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ - .enable_reg = S2MPS11_REG_B9CTRL1, \ - .enable_mask = S2MPS11_ENABLE_MASK \ -} - -#define regulator_desc_s2mps11_buck10 { \ - .name = "BUCK10", \ - .id = S2MPS11_BUCK10, \ - .ops = &s2mps11_buck_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = S2MPS11_BUCK_MIN2, \ - .uV_step = S2MPS11_BUCK_STEP2, \ - .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ - .ramp_delay = S2MPS11_RAMP_DELAY, \ - .vsel_reg = S2MPS11_REG_B10CTRL2, \ - .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ - .enable_reg = S2MPS11_REG_B10CTRL1, \ - .enable_mask = S2MPS11_ENABLE_MASK \ -} - static const struct regulator_desc s2mps11_regulators[] = { - regulator_desc_s2mps11_ldo2(1), - regulator_desc_s2mps11_ldo1(2), - regulator_desc_s2mps11_ldo1(3), - regulator_desc_s2mps11_ldo1(4), - regulator_desc_s2mps11_ldo1(5), - regulator_desc_s2mps11_ldo2(6), - regulator_desc_s2mps11_ldo1(7), - regulator_desc_s2mps11_ldo1(8), - regulator_desc_s2mps11_ldo1(9), - regulator_desc_s2mps11_ldo1(10), - regulator_desc_s2mps11_ldo2(11), - regulator_desc_s2mps11_ldo1(12), - regulator_desc_s2mps11_ldo1(13), - regulator_desc_s2mps11_ldo1(14), - regulator_desc_s2mps11_ldo1(15), - regulator_desc_s2mps11_ldo1(16), - regulator_desc_s2mps11_ldo1(17), - regulator_desc_s2mps11_ldo1(18), - regulator_desc_s2mps11_ldo1(19), - regulator_desc_s2mps11_ldo1(20), - regulator_desc_s2mps11_ldo1(21), - regulator_desc_s2mps11_ldo2(22), - regulator_desc_s2mps11_ldo2(23), - regulator_desc_s2mps11_ldo1(24), - regulator_desc_s2mps11_ldo1(25), - regulator_desc_s2mps11_ldo1(26), - regulator_desc_s2mps11_ldo2(27), - regulator_desc_s2mps11_ldo1(28), - regulator_desc_s2mps11_ldo1(29), - regulator_desc_s2mps11_ldo1(30), - regulator_desc_s2mps11_ldo1(31), - regulator_desc_s2mps11_ldo1(32), - regulator_desc_s2mps11_ldo1(33), - regulator_desc_s2mps11_ldo1(34), - regulator_desc_s2mps11_ldo1(35), - regulator_desc_s2mps11_ldo1(36), - regulator_desc_s2mps11_ldo1(37), - regulator_desc_s2mps11_ldo1(38), + regulator_desc_s2mps11_ldo(1, STEP_25_MV), + regulator_desc_s2mps11_ldo(2, STEP_50_MV), + regulator_desc_s2mps11_ldo(3, STEP_50_MV), + regulator_desc_s2mps11_ldo(4, STEP_50_MV), + regulator_desc_s2mps11_ldo(5, STEP_50_MV), + regulator_desc_s2mps11_ldo(6, STEP_25_MV), + regulator_desc_s2mps11_ldo(7, STEP_50_MV), + regulator_desc_s2mps11_ldo(8, STEP_50_MV), + regulator_desc_s2mps11_ldo(9, STEP_50_MV), + regulator_desc_s2mps11_ldo(10, STEP_50_MV), + regulator_desc_s2mps11_ldo(11, STEP_25_MV), + regulator_desc_s2mps11_ldo(12, STEP_50_MV), + regulator_desc_s2mps11_ldo(13, STEP_50_MV), + regulator_desc_s2mps11_ldo(14, STEP_50_MV), + regulator_desc_s2mps11_ldo(15, STEP_50_MV), + regulator_desc_s2mps11_ldo(16, STEP_50_MV), + regulator_desc_s2mps11_ldo(17, STEP_50_MV), + regulator_desc_s2mps11_ldo(18, STEP_50_MV), + regulator_desc_s2mps11_ldo(19, STEP_50_MV), + regulator_desc_s2mps11_ldo(20, STEP_50_MV), + regulator_desc_s2mps11_ldo(21, STEP_50_MV), + regulator_desc_s2mps11_ldo(22, STEP_25_MV), + regulator_desc_s2mps11_ldo(23, STEP_25_MV), + regulator_desc_s2mps11_ldo(24, STEP_50_MV), + regulator_desc_s2mps11_ldo(25, STEP_50_MV), + regulator_desc_s2mps11_ldo(26, STEP_50_MV), + regulator_desc_s2mps11_ldo(27, STEP_25_MV), + regulator_desc_s2mps11_ldo(28, STEP_50_MV), + regulator_desc_s2mps11_ldo(29, STEP_50_MV), + regulator_desc_s2mps11_ldo(30, STEP_50_MV), + regulator_desc_s2mps11_ldo(31, STEP_50_MV), + regulator_desc_s2mps11_ldo(32, STEP_50_MV), + regulator_desc_s2mps11_ldo(33, STEP_50_MV), + regulator_desc_s2mps11_ldo(34, STEP_50_MV), + regulator_desc_s2mps11_ldo(35, STEP_50_MV), + regulator_desc_s2mps11_ldo(36, STEP_50_MV), + regulator_desc_s2mps11_ldo(37, STEP_50_MV), + regulator_desc_s2mps11_ldo(38, STEP_50_MV), regulator_desc_s2mps11_buck1_4(1), regulator_desc_s2mps11_buck1_4(2), regulator_desc_s2mps11_buck1_4(3), regulator_desc_s2mps11_buck1_4(4), regulator_desc_s2mps11_buck5, - regulator_desc_s2mps11_buck6_8(6), - regulator_desc_s2mps11_buck6_8(7), - regulator_desc_s2mps11_buck6_8(8), - regulator_desc_s2mps11_buck9, - regulator_desc_s2mps11_buck10, + regulator_desc_s2mps11_buck6_10(6, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck6_10(7, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck6_10(8, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck6_10(9, MIN_3000_MV, STEP_25_MV), + regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV), }; static int s2mps14_regulator_enable(struct regulator_dev *rdev) @@ -510,56 +464,29 @@ static struct regulator_ops s2mps14_reg_ops = { .set_suspend_disable = s2mps14_regulator_set_suspend_disable, }; -#define regulator_desc_s2mps14_ldo1(num) { \ - .name = "LDO"#num, \ - .id = S2MPS14_LDO##num, \ - .ops = &s2mps14_reg_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = S2MPS14_LDO_MIN_800MV, \ - .uV_step = S2MPS14_LDO_STEP_25MV, \ - .n_voltages = S2MPS14_LDO_N_VOLTAGES, \ - .vsel_reg = S2MPS14_REG_L1CTRL + num - 1, \ - .vsel_mask = S2MPS14_LDO_VSEL_MASK, \ - .enable_reg = S2MPS14_REG_L1CTRL + num - 1, \ - .enable_mask = S2MPS14_ENABLE_MASK \ -} -#define regulator_desc_s2mps14_ldo2(num) { \ - .name = "LDO"#num, \ - .id = S2MPS14_LDO##num, \ - .ops = &s2mps14_reg_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = S2MPS14_LDO_MIN_1800MV, \ - .uV_step = S2MPS14_LDO_STEP_25MV, \ - .n_voltages = S2MPS14_LDO_N_VOLTAGES, \ - .vsel_reg = S2MPS14_REG_L1CTRL + num - 1, \ - .vsel_mask = S2MPS14_LDO_VSEL_MASK, \ - .enable_reg = S2MPS14_REG_L1CTRL + num - 1, \ - .enable_mask = S2MPS14_ENABLE_MASK \ -} -#define regulator_desc_s2mps14_ldo3(num) { \ +#define regulator_desc_s2mps14_ldo(num, min, step) { \ .name = "LDO"#num, \ .id = S2MPS14_LDO##num, \ .ops = &s2mps14_reg_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = S2MPS14_LDO_MIN_800MV, \ - .uV_step = S2MPS14_LDO_STEP_12_5MV, \ + .min_uV = min, \ + .uV_step = step, \ .n_voltages = S2MPS14_LDO_N_VOLTAGES, \ .vsel_reg = S2MPS14_REG_L1CTRL + num - 1, \ .vsel_mask = S2MPS14_LDO_VSEL_MASK, \ .enable_reg = S2MPS14_REG_L1CTRL + num - 1, \ .enable_mask = S2MPS14_ENABLE_MASK \ } -#define regulator_desc_s2mps14_buck1235(num) { \ + +#define regulator_desc_s2mps14_buck(num, min, step) { \ .name = "BUCK"#num, \ .id = S2MPS14_BUCK##num, \ .ops = &s2mps14_reg_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = S2MPS14_BUCK1235_MIN_600MV, \ - .uV_step = S2MPS14_BUCK1235_STEP_6_25MV, \ + .min_uV = min, \ + .uV_step = step, \ .n_voltages = S2MPS14_BUCK_N_VOLTAGES, \ .linear_min_sel = S2MPS14_BUCK1235_START_SEL, \ .ramp_delay = S2MPS14_BUCK_RAMP_DELAY, \ @@ -568,54 +495,38 @@ static struct regulator_ops s2mps14_reg_ops = { .enable_reg = S2MPS14_REG_B1CTRL1 + (num - 1) * 2, \ .enable_mask = S2MPS14_ENABLE_MASK \ } -#define regulator_desc_s2mps14_buck4(num) { \ - .name = "BUCK"#num, \ - .id = S2MPS14_BUCK##num, \ - .ops = &s2mps14_reg_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = S2MPS14_BUCK4_MIN_1400MV, \ - .uV_step = S2MPS14_BUCK4_STEP_12_5MV, \ - .n_voltages = S2MPS14_BUCK_N_VOLTAGES, \ - .linear_min_sel = S2MPS14_BUCK4_START_SEL, \ - .ramp_delay = S2MPS14_BUCK_RAMP_DELAY, \ - .vsel_reg = S2MPS14_REG_B1CTRL2 + (num - 1) * 2, \ - .vsel_mask = S2MPS14_BUCK_VSEL_MASK, \ - .enable_reg = S2MPS14_REG_B1CTRL1 + (num - 1) * 2, \ - .enable_mask = S2MPS14_ENABLE_MASK \ -} static const struct regulator_desc s2mps14_regulators[] = { - regulator_desc_s2mps14_ldo3(1), - regulator_desc_s2mps14_ldo3(2), - regulator_desc_s2mps14_ldo1(3), - regulator_desc_s2mps14_ldo1(4), - regulator_desc_s2mps14_ldo3(5), - regulator_desc_s2mps14_ldo3(6), - regulator_desc_s2mps14_ldo1(7), - regulator_desc_s2mps14_ldo2(8), - regulator_desc_s2mps14_ldo3(9), - regulator_desc_s2mps14_ldo3(10), - regulator_desc_s2mps14_ldo1(11), - regulator_desc_s2mps14_ldo2(12), - regulator_desc_s2mps14_ldo2(13), - regulator_desc_s2mps14_ldo2(14), - regulator_desc_s2mps14_ldo2(15), - regulator_desc_s2mps14_ldo2(16), - regulator_desc_s2mps14_ldo2(17), - regulator_desc_s2mps14_ldo2(18), - regulator_desc_s2mps14_ldo1(19), - regulator_desc_s2mps14_ldo1(20), - regulator_desc_s2mps14_ldo1(21), - regulator_desc_s2mps14_ldo3(22), - regulator_desc_s2mps14_ldo1(23), - regulator_desc_s2mps14_ldo2(24), - regulator_desc_s2mps14_ldo2(25), - regulator_desc_s2mps14_buck1235(1), - regulator_desc_s2mps14_buck1235(2), - regulator_desc_s2mps14_buck1235(3), - regulator_desc_s2mps14_buck4(4), - regulator_desc_s2mps14_buck1235(5), + regulator_desc_s2mps14_ldo(1, MIN_800_MV, STEP_12_5_MV), + regulator_desc_s2mps14_ldo(2, MIN_800_MV, STEP_12_5_MV), + regulator_desc_s2mps14_ldo(3, MIN_800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(4, MIN_800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(5, MIN_800_MV, STEP_12_5_MV), + regulator_desc_s2mps14_ldo(6, MIN_800_MV, STEP_12_5_MV), + regulator_desc_s2mps14_ldo(7, MIN_800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(8, MIN_1800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(9, MIN_800_MV, STEP_12_5_MV), + regulator_desc_s2mps14_ldo(10, MIN_800_MV, STEP_12_5_MV), + regulator_desc_s2mps14_ldo(11, MIN_800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(12, MIN_1800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(13, MIN_1800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(14, MIN_1800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(15, MIN_1800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(16, MIN_1800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(17, MIN_1800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(18, MIN_1800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(19, MIN_800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(20, MIN_800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(21, MIN_800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(22, MIN_800_MV, STEP_12_5_MV), + regulator_desc_s2mps14_ldo(23, MIN_800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(24, MIN_1800_MV, STEP_25_MV), + regulator_desc_s2mps14_ldo(25, MIN_1800_MV, STEP_25_MV), + regulator_desc_s2mps14_buck(1, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps14_buck(2, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps14_buck(3, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps14_buck(4, MIN_1400_MV, STEP_12_5_MV), + regulator_desc_s2mps14_buck(5, MIN_600_MV, STEP_6_25_MV), }; static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11, diff --git a/drivers/regulator/sky81452-regulator.c b/drivers/regulator/sky81452-regulator.c new file mode 100644 index 000000000000..97aff0ccd65f --- /dev/null +++ b/drivers/regulator/sky81452-regulator.c @@ -0,0 +1,130 @@ +/* + * sky81452-regulator.c SKY81452 regulator driver + * + * Copyright 2014 Skyworks Solutions Inc. + * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com> + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that 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, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/of_regulator.h> + +/* registers */ +#define SKY81452_REG1 0x01 +#define SKY81452_REG3 0x03 + +/* bit mask */ +#define SKY81452_LEN 0x40 +#define SKY81452_LOUT 0x1F + +static struct regulator_ops sky81452_reg_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_linear_range sky81452_reg_ranges[] = { + REGULATOR_LINEAR_RANGE(4500000, 0, 14, 250000), + REGULATOR_LINEAR_RANGE(9000000, 15, 31, 1000000), +}; + +static const struct regulator_desc sky81452_reg = { + .name = "LOUT", + .ops = &sky81452_reg_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .n_voltages = SKY81452_LOUT + 1, + .linear_ranges = sky81452_reg_ranges, + .n_linear_ranges = ARRAY_SIZE(sky81452_reg_ranges), + .vsel_reg = SKY81452_REG3, + .vsel_mask = SKY81452_LOUT, + .enable_reg = SKY81452_REG1, + .enable_mask = SKY81452_LEN, +}; + +#ifdef CONFIG_OF +static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev) +{ + struct regulator_init_data *init_data; + struct device_node *np; + + np = of_get_child_by_name(dev->parent->of_node, "regulator"); + if (unlikely(!np)) { + dev_err(dev, "regulator node not found"); + return NULL; + } + + init_data = of_get_regulator_init_data(dev, np); + + of_node_put(np); + return init_data; +} +#else +static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev) +{ + return ERR_PTR(-EINVAL); +} +#endif + +static int sky81452_reg_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct regulator_init_data *init_data = dev_get_platdata(dev); + struct regulator_config config = { }; + struct regulator_dev *rdev; + + if (!init_data) { + init_data = sky81452_reg_parse_dt(dev); + if (IS_ERR(init_data)) + return PTR_ERR(init_data); + } + + config.dev = dev; + config.init_data = init_data; + config.of_node = dev->of_node; + config.regmap = dev_get_drvdata(dev->parent); + + rdev = devm_regulator_register(dev, &sky81452_reg, &config); + if (IS_ERR(rdev)) + return PTR_ERR(rdev); + + platform_set_drvdata(pdev, rdev); + + return 0; +} + +static struct platform_driver sky81452_reg_driver = { + .driver = { + .name = "sky81452-regulator", + }, + .probe = sky81452_reg_probe, +}; + +module_platform_driver(sky81452_reg_driver); + +MODULE_DESCRIPTION("Skyworks SKY81452 Regulator driver"); +MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.0"); diff --git a/drivers/regulator/st-pwm.c b/drivers/regulator/st-pwm.c deleted file mode 100644 index 5ea78df449f8..000000000000 --- a/drivers/regulator/st-pwm.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Regulator driver for ST's PWM Regulators - * - * Copyright (C) 2014 - STMicroelectronics Inc. - * - * Author: Lee Jones <lee.jones@linaro.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/err.h> -#include <linux/regulator/driver.h> -#include <linux/regulator/machine.h> -#include <linux/regulator/of_regulator.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/pwm.h> - -#define ST_PWM_REG_PERIOD 8448 - -struct st_pwm_regulator_pdata { - const struct regulator_desc *desc; - struct st_pwm_voltages *duty_cycle_table; -}; - -struct st_pwm_regulator_data { - const struct st_pwm_regulator_pdata *pdata; - struct pwm_device *pwm; - bool enabled; - int state; -}; - -struct st_pwm_voltages { - unsigned int uV; - unsigned int dutycycle; -}; - -static int st_pwm_regulator_get_voltage_sel(struct regulator_dev *dev) -{ - struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); - - return drvdata->state; -} - -static int st_pwm_regulator_set_voltage_sel(struct regulator_dev *dev, - unsigned selector) -{ - struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); - int dutycycle; - int ret; - - dutycycle = (ST_PWM_REG_PERIOD / 100) * - drvdata->pdata->duty_cycle_table[selector].dutycycle; - - ret = pwm_config(drvdata->pwm, dutycycle, ST_PWM_REG_PERIOD); - if (ret) { - dev_err(&dev->dev, "Failed to configure PWM\n"); - return ret; - } - - drvdata->state = selector; - - if (!drvdata->enabled) { - ret = pwm_enable(drvdata->pwm); - if (ret) { - dev_err(&dev->dev, "Failed to enable PWM\n"); - return ret; - } - drvdata->enabled = true; - } - - return 0; -} - -static int st_pwm_regulator_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); - - if (selector >= dev->desc->n_voltages) - return -EINVAL; - - return drvdata->pdata->duty_cycle_table[selector].uV; -} - -static struct regulator_ops st_pwm_regulator_voltage_ops = { - .set_voltage_sel = st_pwm_regulator_set_voltage_sel, - .get_voltage_sel = st_pwm_regulator_get_voltage_sel, - .list_voltage = st_pwm_regulator_list_voltage, - .map_voltage = regulator_map_voltage_iterate, -}; - -static struct st_pwm_voltages b2105_duty_cycle_table[] = { - { .uV = 1114000, .dutycycle = 0, }, - { .uV = 1095000, .dutycycle = 10, }, - { .uV = 1076000, .dutycycle = 20, }, - { .uV = 1056000, .dutycycle = 30, }, - { .uV = 1036000, .dutycycle = 40, }, - { .uV = 1016000, .dutycycle = 50, }, - /* WARNING: Values above 50% duty-cycle cause boot failures. */ -}; - -static const struct regulator_desc b2105_desc = { - .name = "b2105-pwm-regulator", - .ops = &st_pwm_regulator_voltage_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(b2105_duty_cycle_table), - .supply_name = "pwm", -}; - -static const struct st_pwm_regulator_pdata b2105_info = { - .desc = &b2105_desc, - .duty_cycle_table = b2105_duty_cycle_table, -}; - -static const struct of_device_id st_pwm_of_match[] = { - { .compatible = "st,b2105-pwm-regulator", .data = &b2105_info, }, - { }, -}; -MODULE_DEVICE_TABLE(of, st_pwm_of_match); - -static int st_pwm_regulator_probe(struct platform_device *pdev) -{ - struct st_pwm_regulator_data *drvdata; - struct regulator_dev *regulator; - struct regulator_config config = { }; - struct device_node *np = pdev->dev.of_node; - const struct of_device_id *of_match; - - if (!np) { - dev_err(&pdev->dev, "Device Tree node missing\n"); - return -EINVAL; - } - - drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); - if (!drvdata) - return -ENOMEM; - - of_match = of_match_device(st_pwm_of_match, &pdev->dev); - if (!of_match) { - dev_err(&pdev->dev, "failed to match of device\n"); - return -ENODEV; - } - drvdata->pdata = of_match->data; - - config.init_data = of_get_regulator_init_data(&pdev->dev, np); - if (!config.init_data) - return -ENOMEM; - - config.of_node = np; - config.dev = &pdev->dev; - config.driver_data = drvdata; - - drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); - if (IS_ERR(drvdata->pwm)) { - dev_err(&pdev->dev, "Failed to get PWM\n"); - return PTR_ERR(drvdata->pwm); - } - - regulator = devm_regulator_register(&pdev->dev, - drvdata->pdata->desc, &config); - if (IS_ERR(regulator)) { - dev_err(&pdev->dev, "Failed to register regulator %s\n", - drvdata->pdata->desc->name); - return PTR_ERR(regulator); - } - - return 0; -} - -static struct platform_driver st_pwm_regulator_driver = { - .driver = { - .name = "st-pwm-regulator", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(st_pwm_of_match), - }, - .probe = st_pwm_regulator_probe, -}; - -module_platform_driver(st_pwm_regulator_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); -MODULE_DESCRIPTION("ST PWM Regulator Driver"); -MODULE_ALIAS("platform:st_pwm-regulator"); diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 3ef67a86115c..7380af8bd50d 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -211,9 +211,6 @@ static int tps_65023_probe(struct i2c_client *client, int i; int error; - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EIO; - /** * init_data points to array of regulator_init structures * coming from the board-evm file. diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index d58db72a63b0..adbe4fc5cf07 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -27,10 +27,13 @@ #include <linux/regulator/machine.h> #include <linux/mfd/tps65217.h> -#define TPS65217_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _em, _t, _lr, _nlr) \ +#define TPS65217_REGULATOR(_name, _id, _of_match, _ops, _n, _vr, _vm, _em, \ + _t, _lr, _nlr) \ { \ .name = _name, \ .id = _id, \ + .of_match = of_match_ptr(_of_match), \ + .regulators_node= of_match_ptr("regulators"), \ .ops = &_ops, \ .n_voltages = _n, \ .type = REGULATOR_VOLTAGE, \ @@ -138,87 +141,40 @@ static struct regulator_ops tps65217_pmic_ldo1_ops = { }; static const struct regulator_desc regulators[] = { - TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, tps65217_pmic_ops, 64, - TPS65217_REG_DEFDCDC1, TPS65217_DEFDCDCX_DCDC_MASK, - TPS65217_ENABLE_DC1_EN, NULL, tps65217_uv1_ranges, - 2), /* DCDC1 voltage range: 900000 ~ 1800000 */ - TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, tps65217_pmic_ops, 64, - TPS65217_REG_DEFDCDC2, TPS65217_DEFDCDCX_DCDC_MASK, - TPS65217_ENABLE_DC2_EN, NULL, tps65217_uv1_ranges, + TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, "dcdc1", + tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC1, + TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC1_EN, + NULL, tps65217_uv1_ranges, 2), + TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, "dcdc2", + tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC2, + TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC2_EN, + NULL, tps65217_uv1_ranges, ARRAY_SIZE(tps65217_uv1_ranges)), - TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, tps65217_pmic_ops, 64, - TPS65217_REG_DEFDCDC3, TPS65217_DEFDCDCX_DCDC_MASK, - TPS65217_ENABLE_DC3_EN, NULL, tps65217_uv1_ranges, - 1), /* DCDC3 voltage range: 900000 ~ 1500000 */ - TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, tps65217_pmic_ldo1_ops, 16, - TPS65217_REG_DEFLDO1, TPS65217_DEFLDO1_LDO1_MASK, - TPS65217_ENABLE_LDO1_EN, LDO1_VSEL_table, NULL, 0), - TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, tps65217_pmic_ops, 64, - TPS65217_REG_DEFLDO2, TPS65217_DEFLDO2_LDO2_MASK, - TPS65217_ENABLE_LDO2_EN, NULL, tps65217_uv1_ranges, + TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, "dcdc3", + tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC3, + TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC3_EN, + NULL, tps65217_uv1_ranges, 1), + TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, "ldo1", + tps65217_pmic_ldo1_ops, 16, TPS65217_REG_DEFLDO1, + TPS65217_DEFLDO1_LDO1_MASK, TPS65217_ENABLE_LDO1_EN, + LDO1_VSEL_table, NULL, 0), + TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, "ldo2", tps65217_pmic_ops, + 64, TPS65217_REG_DEFLDO2, + TPS65217_DEFLDO2_LDO2_MASK, TPS65217_ENABLE_LDO2_EN, + NULL, tps65217_uv1_ranges, ARRAY_SIZE(tps65217_uv1_ranges)), - TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, tps65217_pmic_ops, 32, - TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK, + TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, "ldo3", tps65217_pmic_ops, + 32, TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK, TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN, NULL, tps65217_uv2_ranges, ARRAY_SIZE(tps65217_uv2_ranges)), - TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, tps65217_pmic_ops, 32, - TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK, + TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, "ldo4", tps65217_pmic_ops, + 32, TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK, TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN, NULL, tps65217_uv2_ranges, ARRAY_SIZE(tps65217_uv2_ranges)), }; -#ifdef CONFIG_OF -static struct of_regulator_match reg_matches[] = { - { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, - { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, - { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, - { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, - { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, - { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, - { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, -}; - -static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) -{ - struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); - struct device_node *node = tps->dev->of_node; - struct tps65217_board *pdata; - struct device_node *regs; - int i, count; - - regs = of_get_child_by_name(node, "regulators"); - if (!regs) - return NULL; - - count = of_regulator_match(&pdev->dev, regs, reg_matches, - TPS65217_NUM_REGULATOR); - of_node_put(regs); - if ((count < 0) || (count > TPS65217_NUM_REGULATOR)) - return NULL; - - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - - for (i = 0; i < count; i++) { - if (!reg_matches[i].of_node) - continue; - - pdata->tps65217_init_data[i] = reg_matches[i].init_data; - pdata->of_node[i] = reg_matches[i].of_node; - } - - return pdata; -} -#else -static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) -{ - return NULL; -} -#endif - static int tps65217_regulator_probe(struct platform_device *pdev) { struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); @@ -227,14 +183,6 @@ static int tps65217_regulator_probe(struct platform_device *pdev) struct regulator_config config = { }; int i; - if (tps->dev->of_node) - pdata = tps65217_parse_dt(pdev); - - if (!pdata) { - dev_err(&pdev->dev, "Platform data not found\n"); - return -EINVAL; - } - if (tps65217_chip_id(tps) != TPS65217) { dev_err(&pdev->dev, "Invalid tps chip version\n"); return -ENODEV; @@ -245,11 +193,10 @@ static int tps65217_regulator_probe(struct platform_device *pdev) for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { /* Register the regulators */ config.dev = tps->dev; - config.init_data = pdata->tps65217_init_data[i]; + if (pdata) + config.init_data = pdata->tps65217_init_data[i]; config.driver_data = tps; config.regmap = tps->regmap; - if (tps->dev->of_node) - config.of_node = pdata->of_node[i]; rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); @@ -259,6 +206,7 @@ static int tps65217_regulator_probe(struct platform_device *pdev) return PTR_ERR(rdev); } } + return 0; } diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index e584c998b55f..18fc991175bc 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -1047,7 +1047,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( *tps65910_reg_matches = matches; for (idx = 0; idx < count; idx++) { - if (!matches[idx].init_data || !matches[idx].of_node) + if (!matches[idx].of_node) continue; pmic_plat_data->tps65910_pmic_init_data[idx] = @@ -1077,7 +1077,6 @@ static int tps65910_probe(struct platform_device *pdev) struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); struct regulator_config config = { }; struct tps_info *info; - struct regulator_init_data *reg_data; struct regulator_dev *rdev; struct tps65910_reg *pmic; struct tps65910_board *pmic_plat_data; @@ -1140,14 +1139,6 @@ static int tps65910_probe(struct platform_device *pdev) for (i = 0; i < pmic->num_regulators && i < TPS65910_NUM_REGS; i++, info++) { - - reg_data = pmic_plat_data->tps65910_pmic_init_data[i]; - - /* Regulator API handles empty constraints but not NULL - * constraints */ - if (!reg_data) - continue; - /* Register the regulators */ pmic->info[i] = info; @@ -1199,7 +1190,7 @@ static int tps65910_probe(struct platform_device *pdev) pmic->desc[i].enable_mask = TPS65910_SUPPLY_STATE_ENABLED; config.dev = tps65910->dev; - config.init_data = reg_data; + config.init_data = pmic_plat_data->tps65910_pmic_init_data[i]; config.driver_data = pmic; config.regmap = tps65910->regmap; diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 79788a12712d..02e69e7ee4a3 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -1647,7 +1647,7 @@ static int cxgbi_inet6addr_handler(struct notifier_block *this, if (event_dev->priv_flags & IFF_802_1Q_VLAN) event_dev = vlan_dev_real_dev(event_dev); - cdev = cxgbi_device_find_by_netdev(event_dev, NULL); + cdev = cxgbi_device_find_by_netdev_rcu(event_dev, NULL); if (!cdev) return ret; diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index d65df6dc106f..addd1dddce14 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -57,6 +57,9 @@ MODULE_PARM_DESC(dbg_level, "libiscsi debug level (default=0)"); static LIST_HEAD(cdev_list); static DEFINE_MUTEX(cdev_mutex); +static LIST_HEAD(cdev_rcu_list); +static DEFINE_SPINLOCK(cdev_rcu_lock); + int cxgbi_device_portmap_create(struct cxgbi_device *cdev, unsigned int base, unsigned int max_conn) { @@ -142,6 +145,10 @@ struct cxgbi_device *cxgbi_device_register(unsigned int extra, list_add_tail(&cdev->list_head, &cdev_list); mutex_unlock(&cdev_mutex); + spin_lock(&cdev_rcu_lock); + list_add_tail_rcu(&cdev->rcu_node, &cdev_rcu_list); + spin_unlock(&cdev_rcu_lock); + log_debug(1 << CXGBI_DBG_DEV, "cdev 0x%p, p# %u.\n", cdev, nports); return cdev; @@ -153,9 +160,16 @@ void cxgbi_device_unregister(struct cxgbi_device *cdev) log_debug(1 << CXGBI_DBG_DEV, "cdev 0x%p, p# %u,%s.\n", cdev, cdev->nports, cdev->nports ? cdev->ports[0]->name : ""); + mutex_lock(&cdev_mutex); list_del(&cdev->list_head); mutex_unlock(&cdev_mutex); + + spin_lock(&cdev_rcu_lock); + list_del_rcu(&cdev->rcu_node); + spin_unlock(&cdev_rcu_lock); + synchronize_rcu(); + cxgbi_device_destroy(cdev); } EXPORT_SYMBOL_GPL(cxgbi_device_unregister); @@ -167,12 +181,9 @@ void cxgbi_device_unregister_all(unsigned int flag) mutex_lock(&cdev_mutex); list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) { if ((cdev->flags & flag) == flag) { - log_debug(1 << CXGBI_DBG_DEV, - "cdev 0x%p, p# %u,%s.\n", - cdev, cdev->nports, cdev->nports ? - cdev->ports[0]->name : ""); - list_del(&cdev->list_head); - cxgbi_device_destroy(cdev); + mutex_unlock(&cdev_mutex); + cxgbi_device_unregister(cdev); + mutex_lock(&cdev_mutex); } } mutex_unlock(&cdev_mutex); @@ -191,6 +202,7 @@ struct cxgbi_device *cxgbi_device_find_by_lldev(void *lldev) } } mutex_unlock(&cdev_mutex); + log_debug(1 << CXGBI_DBG_DEV, "lldev 0x%p, NO match found.\n", lldev); return NULL; @@ -230,6 +242,39 @@ struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev, } EXPORT_SYMBOL_GPL(cxgbi_device_find_by_netdev); +struct cxgbi_device *cxgbi_device_find_by_netdev_rcu(struct net_device *ndev, + int *port) +{ + struct net_device *vdev = NULL; + struct cxgbi_device *cdev; + int i; + + if (ndev->priv_flags & IFF_802_1Q_VLAN) { + vdev = ndev; + ndev = vlan_dev_real_dev(ndev); + pr_info("vlan dev %s -> %s.\n", vdev->name, ndev->name); + } + + rcu_read_lock(); + list_for_each_entry_rcu(cdev, &cdev_rcu_list, rcu_node) { + for (i = 0; i < cdev->nports; i++) { + if (ndev == cdev->ports[i]) { + cdev->hbas[i]->vdev = vdev; + rcu_read_unlock(); + if (port) + *port = i; + return cdev; + } + } + } + rcu_read_unlock(); + + log_debug(1 << CXGBI_DBG_DEV, + "ndev 0x%p, %s, NO match found.\n", ndev, ndev->name); + return NULL; +} +EXPORT_SYMBOL_GPL(cxgbi_device_find_by_netdev_rcu); + static struct cxgbi_device *cxgbi_device_find_by_mac(struct net_device *ndev, int *port) { diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index b3e6e7541cc5..1d98fad6a0ab 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -527,6 +527,7 @@ struct cxgbi_ports_map { #define CXGBI_FLAG_IPV4_SET 0x10 struct cxgbi_device { struct list_head list_head; + struct list_head rcu_node; unsigned int flags; struct net_device **ports; void *lldev; @@ -709,6 +710,8 @@ void cxgbi_device_unregister(struct cxgbi_device *); void cxgbi_device_unregister_all(unsigned int flag); struct cxgbi_device *cxgbi_device_find_by_lldev(void *); struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *, int *); +struct cxgbi_device *cxgbi_device_find_by_netdev_rcu(struct net_device *, + int *); int cxgbi_hbas_add(struct cxgbi_device *, u64, unsigned int, struct scsi_host_template *, struct scsi_transport_template *); diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 1d42dba6121d..bd672948f2f1 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -3587,7 +3587,7 @@ static void __used s8250_options(void) #ifdef CONFIG_SERIAL_8250_RSA __module_param_call(MODULE_PARAM_PREFIX, probe_rsa, ¶m_array_ops, .arr = &__param_arr_probe_rsa, - 0444, -1); + 0444, -1, 0); #endif } #else diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 3f42785f653c..9bfa7252f7f9 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -970,6 +970,13 @@ static struct scsi_host_template uas_host_template = { .cmd_per_lun = 1, /* until we override it */ .skip_settle_delay = 1, .ordered_tag = 1, + + /* + * The uas drivers expects tags not to be bigger than the maximum + * per-device queue depth, which is not true with the blk-mq tag + * allocator. + */ + .disable_blk_mq = true, }; #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ |