[PATCH v4 1/1] usb: gadget: f_fs: Add support for SuperSpeed Mode
Allow userspace to pass SuperSpeed descriptors and handle them in the driver accordingly. This change doesn't modify existing desc_header and thereby keeps the ABI changes backward compatible i.e. existing userspace drivers compiled with old header (functionfs.h) would continue to work with the updated kernel. Change-Id: Ic27035fdef2a83828024348d75be1518e9f8c5c6 Signed-off-by: Manu Gautam mgau...@codeaurora.org --- drivers/usb/gadget/f_fs.c | 176 +++--- drivers/usb/gadget/u_fs.h | 8 ++- 2 files changed, 142 insertions(+), 42 deletions(-) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 306a2b5..8c7bf04 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -122,8 +122,8 @@ struct ffs_ep { struct usb_ep *ep;/* P: ffs-eps_lock */ struct usb_request *req; /* P: epfile-mutex */ - /* [0]: full speed, [1]: high speed */ - struct usb_endpoint_descriptor *descs[2]; + /* [0]: full speed, [1]: high speed, [2]: super speed */ + struct usb_endpoint_descriptor *descs[3]; u8 num; @@ -1184,9 +1184,12 @@ static void ffs_data_reset(struct ffs_data *ffs) ffs-stringtabs = NULL; ffs-raw_descs_length = 0; - ffs-raw_fs_descs_length = 0; + ffs-raw_fs_hs_descs_length = 0; + ffs-raw_ss_descs_offset = 0; + ffs-raw_ss_descs_length = 0; ffs-fs_descs_count = 0; ffs-hs_descs_count = 0; + ffs-ss_descs_count = 0; ffs-strings_count = 0; ffs-interfaces_count = 0; @@ -1329,7 +1332,24 @@ static int ffs_func_eps_enable(struct ffs_function *func) spin_lock_irqsave(func-ffs-eps_lock, flags); do { struct usb_endpoint_descriptor *ds; - ds = ep-descs[ep-descs[1] ? 1 : 0]; + int desc_idx; + + if (ffs-gadget-speed == USB_SPEED_SUPER) + desc_idx = 2; + else if (ffs-gadget-speed == USB_SPEED_HIGH) + desc_idx = 1; + else + desc_idx = 0; + + /* fall-back to lower speed if desc missing for current speed */ + do { + ds = ep-descs[desc_idx]; + } while (!ds --desc_idx = 0); + + if (!ds) { + ret = -EINVAL; + break; + } ep-ep-driver_data = ep; ep-ep-desc = ds; @@ -1464,6 +1484,12 @@ static int __must_check ffs_do_desc(char *data, unsigned len, } break; + case USB_DT_SS_ENDPOINT_COMP: + pr_vdebug(EP SS companion descriptor\n); + if (length != sizeof(struct usb_ss_ep_comp_descriptor)) + goto inv_length; + break; + case USB_DT_OTHER_SPEED_CONFIG: case USB_DT_INTERFACE_POWER: case USB_DT_DEBUG: @@ -1574,8 +1600,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, static int __ffs_data_got_descs(struct ffs_data *ffs, char *const _data, size_t len) { - unsigned fs_count, hs_count; - int fs_len, ret = -EINVAL; + unsigned fs_count, hs_count, ss_count = 0; + int fs_len, hs_len, ss_len, ret = -EINVAL; char *data = _data; ENTER(); @@ -1586,9 +1612,6 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, fs_count = get_unaligned_le32(data + 8); hs_count = get_unaligned_le32(data + 12); - if (!fs_count !hs_count) - goto einval; - data += 16; len -= 16; @@ -1607,22 +1630,58 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, } if (likely(hs_count)) { - ret = ffs_do_descs(hs_count, data, len, + hs_len = ffs_do_descs(hs_count, data, len, __ffs_data_do_entity, ffs); - if (unlikely(ret 0)) + if (unlikely(hs_len 0)) { + ret = hs_len; + goto error; + } + + data += hs_len; + len -= hs_len; + } else { + hs_len = 0; + } + + if (len = 8) { + /* Check SS_MAGIC for presence of ss_descs and get SS_COUNT */ + if (get_unaligned_le32(data) != FUNCTIONFS_SS_DESC_MAGIC) + goto einval; + + ss_count = get_unaligned_le32(data + 4); + data += 8; + len -= 8; + } + + if (!fs_count !hs_count !ss_count) + goto einval; + + if (ss_count) { + ss_len = ffs_do_descs(ss_count, data, len, + __ffs_data_do_entity, ffs); + if (unlikely(ss_len 0)) { + ret = ss_len;
Re: [PATCH v4 1/1] usb: gadget: f_fs: Add support for SuperSpeed Mode
On Mon, Dec 23, 2013 at 05:18:42PM +0530, Manu Gautam wrote: Allow userspace to pass SuperSpeed descriptors and handle them in the driver accordingly. This change doesn't modify existing desc_header and thereby keeps the ABI changes backward compatible i.e. existing userspace drivers compiled with old header (functionfs.h) would continue to work with the updated kernel. Change-Id: Ic27035fdef2a83828024348d75be1518e9f8c5c6 when sending patches upstream, please remove gerrit garbage from commit log ;-) I'll wait for Michal to review this one. -- balbi signature.asc Description: Digital signature
Re: [PATCH] regmap: Allow regmap_bulk_write() to work for no-bus regmaps
On 12/18/13 10:45, Mark Brown wrote: On Mon, Dec 16, 2013 at 06:30:47PM -0800, Stephen Boyd wrote: -/* No formatting is require if val_byte is 1 */ -if (val_bytes == 1) { -wval = (void *)val; +ival = *(unsigned int *)(val + (i * val_bytes)); +ret = _regmap_write(map, reg + (i * map-reg_stride), +ival); +if (ret != 0) +goto out; This doesn't quite work - val is an array of objects of the size of the size of a register not of unsigned integers so you're parsing extra data out there. That possibly wasn't the best choice of API but we have quite a few users now so ick. Are you concerned that we'll read past the end of the val buffer? Do we need to cast the pointer to be the appropriate size according to val_bytes? Something like this? for (i = 0; i val_count; i++) { unsigned int ival; switch (val_bytes) { case 1: ival = *(u8 *)(val + (i * val_bytes)); break; case 2: ival = *(u16 *)(val + (i * val_bytes)); break; case 4: ival = *(u32 *)(val + (i * val_bytes)); break; #ifdef CONFIG_64BIT case 8: ival = *(u64 *)(val + (i * val_bytes)); break; #endif default: ret = -EINVAL; goto out; } ret = _regmap_write(map, reg + (i * map-reg_stride), ival); if (ret != 0) goto out; } -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 4/7] mfd: ssbi: Add regmap read/write helpers
Add read and write helper functions that the pm8921-core driver can use to read and write ssbi regsiters via a no-bus regmap. Cc: Mark Brown broo...@kernel.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- drivers/mfd/ssbi.c | 13 + include/linux/ssbi.h | 3 +++ 2 files changed, 16 insertions(+) diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c index b78942e..c5d270f 100644 --- a/drivers/mfd/ssbi.c +++ b/drivers/mfd/ssbi.c @@ -269,6 +269,19 @@ int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len) } EXPORT_SYMBOL_GPL(ssbi_write); +int ssbi_reg_read(void *context, unsigned int reg, unsigned int *val) +{ + *val = 0; + return ssbi_read(context, reg, (u8 *)val, 1); +} +EXPORT_SYMBOL_GPL(ssbi_reg_read); + +int ssbi_reg_write(void *context, unsigned int reg, unsigned int val) +{ + return ssbi_write(context, reg, (u8 *)val, 1); +} +EXPORT_SYMBOL_GPL(ssbi_reg_write); + static int ssbi_probe(struct platform_device *pdev) { struct device_node *np = pdev-dev.of_node; diff --git a/include/linux/ssbi.h b/include/linux/ssbi.h index bcbb642..b862f3d 100644 --- a/include/linux/ssbi.h +++ b/include/linux/ssbi.h @@ -20,4 +20,7 @@ int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len); int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len); +int ssbi_reg_read(void *context, unsigned int reg, unsigned int *val); +int ssbi_reg_write(void *context, unsigned int reg, unsigned int val); + #endif -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 6/7] mfd: pm8921: Add DT match table
Allow this driver to probe based on devicetree. Signed-off-by: Stephen Boyd sb...@codeaurora.org --- drivers/mfd/pm8921-core.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c index d13cb6e..290f0da 100644 --- a/drivers/mfd/pm8921-core.c +++ b/drivers/mfd/pm8921-core.c @@ -420,6 +420,13 @@ static const struct regmap_config ssbi_regmap_config = { .reg_write = ssbi_reg_write }; +static const struct of_device_id pm8921_id_table[] = { + { .compatible = qcom,pm8058, }, + { .compatible = qcom,pm8921, }, + { } +}; +MODULE_DEVICE_TABLE(of, pm8921_id_table); + static int pm8921_probe(struct platform_device *pdev) { struct pm8921 *pmic; @@ -429,7 +436,6 @@ static int pm8921_probe(struct platform_device *pdev) unsigned int irq; u32 rev; - irq = platform_get_irq(pdev, 0); if (irq 0) return irq; @@ -494,6 +500,7 @@ static struct platform_driver pm8921_driver = { .driver = { .name = pm8921-core, .owner = THIS_MODULE, + .of_match_table = pm8921_id_table, }, }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/7] mfd: Move pm8xxx-irq.c contents into only driver that uses it
The pm8xxx-irq.c code is practically mandatory given that the pm8921-core driver will WARN about it missing and the Kconfig marks it as default y when a PM8xxx chips is enabled. The only reason the file was split out was because we planned to support other pm8xxx chips with different pm8xxx-core.c files. Now that we have DT on ARM this isn't necessary because we should be able to support all the ssbi based PM8xxx chips in one driver and one file with no data bloat. Let's move this code into the only driver that uses it right now (pm8921) so that it's always compiled when needed. In the future we can rename pm8921-core.c to something more generic. Signed-off-by: Stephen Boyd sb...@codeaurora.org --- drivers/mfd/Kconfig| 10 -- drivers/mfd/pm8921-core.c | 348 ++ drivers/mfd/pm8xxx-irq.c | 371 - include/linux/mfd/pm8xxx/irq.h | 23 --- 4 files changed, 348 insertions(+), 404 deletions(-) delete mode 100644 drivers/mfd/pm8xxx-irq.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 914c3d1..9ee4ce6 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -466,16 +466,6 @@ config MFD_PM8921_CORE Say M here if you want to include support for PM8921 chip as a module. This will build a module called pm8921-core. -config MFD_PM8XXX_IRQ - bool Qualcomm PM8xxx IRQ features - depends on MFD_PM8XXX - default y if MFD_PM8XXX - help - This is the IRQ driver for Qualcomm PM 8xxx PMIC chips. - - This is required to use certain other PM 8xxx features, such as GPIO - and MPP. - config MFD_RDC321X tristate RDC R-321x southbridge select MFD_CORE diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c index a6841f7..669f8f2 100644 --- a/drivers/mfd/pm8921-core.c +++ b/drivers/mfd/pm8921-core.c @@ -14,6 +14,8 @@ #define pr_fmt(fmt) %s: fmt, __func__ #include linux/kernel.h +#include linux/interrupt.h +#include linux/irq.h #include linux/module.h #include linux/platform_device.h #include linux/slab.h @@ -22,15 +24,361 @@ #include linux/mfd/core.h #include linux/mfd/pm8xxx/pm8921.h #include linux/mfd/pm8xxx/core.h +#include linux/mfd/pm8xxx/irq.h + +#defineSSBI_REG_ADDR_IRQ_BASE 0x1BB + +#defineSSBI_REG_ADDR_IRQ_ROOT (SSBI_REG_ADDR_IRQ_BASE + 0) +#defineSSBI_REG_ADDR_IRQ_M_STATUS1 (SSBI_REG_ADDR_IRQ_BASE + 1) +#defineSSBI_REG_ADDR_IRQ_M_STATUS2 (SSBI_REG_ADDR_IRQ_BASE + 2) +#defineSSBI_REG_ADDR_IRQ_M_STATUS3 (SSBI_REG_ADDR_IRQ_BASE + 3) +#defineSSBI_REG_ADDR_IRQ_M_STATUS4 (SSBI_REG_ADDR_IRQ_BASE + 4) +#defineSSBI_REG_ADDR_IRQ_BLK_SEL (SSBI_REG_ADDR_IRQ_BASE + 5) +#defineSSBI_REG_ADDR_IRQ_IT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 6) +#defineSSBI_REG_ADDR_IRQ_CONFIG(SSBI_REG_ADDR_IRQ_BASE + 7) +#defineSSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8) + +#definePM_IRQF_LVL_SEL 0x01/* level select */ +#definePM_IRQF_MASK_FE 0x02/* mask falling edge */ +#definePM_IRQF_MASK_RE 0x04/* mask rising edge */ +#definePM_IRQF_CLR 0x08/* clear interrupt */ +#definePM_IRQF_BITS_MASK 0x70 +#definePM_IRQF_BITS_SHIFT 4 +#definePM_IRQF_WRITE 0x80 + +#definePM_IRQF_MASK_ALL(PM_IRQF_MASK_FE | \ + PM_IRQF_MASK_RE) #define REG_HWREV 0x002 /* PMIC4 revision */ #define REG_HWREV_20x0E8 /* PMIC4 revision 2 */ +struct pm_irq_chip { + struct device *dev; + spinlock_t pm_irq_lock; + unsigned intdevirq; + unsigned intirq_base; + unsigned intnum_irqs; + unsigned intnum_blocks; + unsigned intnum_masters; + u8 config[0]; +}; + struct pm8921 { struct device *dev; struct pm_irq_chip *irq_chip; }; +static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp) +{ + return pm8xxx_readb(chip-dev, SSBI_REG_ADDR_IRQ_ROOT, rp); +} + +static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp) +{ + return pm8xxx_readb(chip-dev, + SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp); +} + +static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip) +{ + int rc; + + spin_lock(chip-pm_irq_lock); + rc = pm8xxx_writeb(chip-dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); + if (rc) { + pr_err(Failed Selecting Block %d rc=%d\n, bp, rc); + goto bail; + } + + rc = pm8xxx_readb(chip-dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip); + if
[PATCH v2 5/7] mfd: pm8921: Use ssbi regmap
Use a regmap so that the pm8xxx read/write APIs can be removed once all consumer drivers are converted. Cc: Mark Brown broo...@kernel.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- drivers/mfd/Kconfig | 1 + drivers/mfd/pm8921-core.c | 72 +++ 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 35007ed..e4a3ae2 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -455,6 +455,7 @@ config MFD_PM8921_CORE depends on (ARCH_MSM || HEXAGON) select MFD_CORE select MFD_PM8XXX + select REGMAP help If you say yes to this option, support will be included for the built-in PM8921 PMIC chip. diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c index 5d1d509..d13cb6e 100644 --- a/drivers/mfd/pm8921-core.c +++ b/drivers/mfd/pm8921-core.c @@ -23,6 +23,7 @@ #include linux/slab.h #include linux/err.h #include linux/ssbi.h +#include linux/regmap.h #include linux/of_platform.h #include linux/mfd/core.h #include linux/mfd/pm8xxx/core.h @@ -55,6 +56,7 @@ struct pm_irq_chip { struct device *dev; + struct regmap *regmap; spinlock_t pm_irq_lock; struct irq_domain *domain; unsigned intnum_irqs; @@ -68,29 +70,19 @@ struct pm8921 { struct pm_irq_chip *irq_chip; }; -static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp) -{ - return pm8xxx_readb(chip-dev, SSBI_REG_ADDR_IRQ_ROOT, rp); -} - -static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp) -{ - return pm8xxx_readb(chip-dev, - SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp); -} - -static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip) +static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp, +unsigned int *ip) { int rc; spin_lock(chip-pm_irq_lock); - rc = pm8xxx_writeb(chip-dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); + rc = regmap_write(chip-regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); if (rc) { pr_err(Failed Selecting Block %d rc=%d\n, bp, rc); goto bail; } - rc = pm8xxx_readb(chip-dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip); + rc = regmap_read(chip-regmap, SSBI_REG_ADDR_IRQ_IT_STATUS, ip); if (rc) pr_err(Failed Reading Status rc=%d\n, rc); bail: @@ -98,19 +90,20 @@ bail: return rc; } -static int pm8xxx_config_irq(struct pm_irq_chip *chip, u8 bp, u8 cp) +static int +pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp) { int rc; spin_lock(chip-pm_irq_lock); - rc = pm8xxx_writeb(chip-dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); + rc = regmap_write(chip-regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp); if (rc) { pr_err(Failed Selecting Block %d rc=%d\n, bp, rc); goto bail; } cp |= PM_IRQF_WRITE; - rc = pm8xxx_writeb(chip-dev, SSBI_REG_ADDR_IRQ_CONFIG, cp); + rc = regmap_write(chip-regmap, SSBI_REG_ADDR_IRQ_CONFIG, cp); if (rc) pr_err(Failed Configuring IRQ rc=%d\n, rc); bail: @@ -121,7 +114,7 @@ bail: static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block) { int pmirq, irq, i, ret = 0; - u8 bits; + unsigned int bits; ret = pm8xxx_read_block_irq(chip, block, bits); if (ret) { @@ -146,10 +139,11 @@ static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block) static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master) { - u8 blockbits; + unsigned int blockbits; int block_number, i, ret = 0; - ret = pm8xxx_read_master_irq(chip, master, blockbits); + ret = regmap_read(chip-regmap, SSBI_REG_ADDR_IRQ_M_STATUS1 + master, + blockbits); if (ret) { pr_err(Failed to read master %d ret=%d\n, master, ret); return ret; @@ -171,12 +165,12 @@ static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc) { struct pm_irq_chip *chip = irq_desc_get_handler_data(desc); struct irq_chip *irq_chip = irq_desc_get_chip(desc); - u8 root; + unsigned int root; int i, ret, masters = 0; chained_irq_enter(irq_chip, desc); - ret = pm8xxx_read_root_irq(chip, root); + ret = regmap_read(chip-regmap, SSBI_REG_ADDR_IRQ_ROOT, root); if (ret) { pr_err(Can't read root status ret=%d\n, ret); return; @@ -281,7 +275,7 @@ static struct irq_chip pm8xxx_irq_chip = { static int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq) { int pmirq, rc; - u8 block, bits, bit; + unsigned int block, bits, bit;
[PATCH v2 3/7] mfd: pm8921: Migrate to irqdomains
Convert this driver to use irqdomains so that the PMIC's child devices can be converted to devicetree. Signed-off-by: Stephen Boyd sb...@codeaurora.org --- drivers/mfd/pm8921-core.c | 184 ++ include/linux/mfd/pm8xxx/irq.h| 36 include/linux/mfd/pm8xxx/pm8921.h | 30 --- 3 files changed, 65 insertions(+), 185 deletions(-) delete mode 100644 include/linux/mfd/pm8xxx/irq.h delete mode 100644 include/linux/mfd/pm8xxx/pm8921.h diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c index 7964932..5d1d509 100644 --- a/drivers/mfd/pm8921-core.c +++ b/drivers/mfd/pm8921-core.c @@ -17,15 +17,15 @@ #include linux/interrupt.h #include linux/irqchip/chained_irq.h #include linux/irq.h +#include linux/irqdomain.h #include linux/module.h #include linux/platform_device.h #include linux/slab.h #include linux/err.h #include linux/ssbi.h +#include linux/of_platform.h #include linux/mfd/core.h -#include linux/mfd/pm8xxx/pm8921.h #include linux/mfd/pm8xxx/core.h -#include linux/mfd/pm8xxx/irq.h #defineSSBI_REG_ADDR_IRQ_BASE 0x1BB @@ -56,8 +56,7 @@ struct pm_irq_chip { struct device *dev; spinlock_t pm_irq_lock; - unsigned intdevirq; - unsigned intirq_base; + struct irq_domain *domain; unsigned intnum_irqs; unsigned intnum_blocks; unsigned intnum_masters; @@ -138,7 +137,7 @@ static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block) for (i = 0; i 8; i++) { if (bits (1 i)) { pmirq = block * 8 + i; - irq = pmirq + chip-irq_base; + irq = irq_find_mapping(chip-domain, pmirq); generic_handle_irq(irq); } } @@ -197,12 +196,11 @@ static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc) static void pm8xxx_irq_mask_ack(struct irq_data *d) { struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d); - unsigned int pmirq = d-irq - chip-irq_base; - int master, irq_bit; + unsigned int pmirq = irqd_to_hwirq(d); + int irq_bit; u8 block, config; block = pmirq / 8; - master = block / 8; irq_bit = pmirq % 8; config = chip-config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR; @@ -212,12 +210,11 @@ static void pm8xxx_irq_mask_ack(struct irq_data *d) static void pm8xxx_irq_unmask(struct irq_data *d) { struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d); - unsigned int pmirq = d-irq - chip-irq_base; - int master, irq_bit; + unsigned int pmirq = irqd_to_hwirq(d); + int irq_bit; u8 block, config; block = pmirq / 8; - master = block / 8; irq_bit = pmirq % 8; config = chip-config[pmirq]; @@ -227,12 +224,11 @@ static void pm8xxx_irq_unmask(struct irq_data *d) static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type) { struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d); - unsigned int pmirq = d-irq - chip-irq_base; - int master, irq_bit; + unsigned int pmirq = irqd_to_hwirq(d); + int irq_bit; u8 block, config; block = pmirq / 8; - master = block / 8; irq_bit = pmirq % 8; chip-config[pmirq] = (irq_bit PM_IRQF_BITS_SHIFT) @@ -287,12 +283,9 @@ static int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq) int pmirq, rc; u8 block, bits, bit; unsigned long flags; + struct irq_data *irq_data = irq_get_irq_data(irq); - if (chip == NULL || irq chip-irq_base || - irq = chip-irq_base + chip-num_irqs) - return -EINVAL; - - pmirq = irq - chip-irq_base; + pmirq = irq_data-hwirq; block = pmirq / 8; bit = pmirq % 8; @@ -321,64 +314,55 @@ bail_out: return rc; } -static struct pm_irq_chip *pm8xxx_irq_init(struct device *dev, - const struct pm8xxx_irq_platform_data *pdata) +static struct lock_class_key pm8xxx_irq_lock_class; + +static int pm8xxx_irq_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) { - struct pm_irq_chip *chip; - int devirq, rc; - unsigned int pmirq; + struct pm_irq_chip *chip = d-host_data; - if (!pdata) { - pr_err(No platform data\n); - return ERR_PTR(-EINVAL); - } + irq_set_lockdep_class(irq, pm8xxx_irq_lock_class); + irq_set_chip_and_handler(irq, pm8xxx_irq_chip, handle_level_irq); + irq_set_chip_data(irq, chip); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif + return 0; +} - devirq =
[PATCH v2 2/7] mfd: pm8921: Update for genirq changes
Since this code has been marked broken for some time a few genirq tree wide changes weren't made. set_irq_wake() was renamed to irq_set_irq_wake() in commit a0cd9ca2b (genirq: Namespace cleanup, 2011-02-10) and commit 10a8c383 (irq: introduce entry and exit functions for chained handlers) introduced the chained irq functions but this driver wasn't updated to use them. Fix these problems and remove the BROKEN marking on this driver. Acked-by: Lee Jones lee.jo...@linaro.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- drivers/mfd/Kconfig | 1 - drivers/mfd/pm8921-core.c | 7 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9ee4ce6..35007ed 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -453,7 +453,6 @@ config MFD_PM8XXX config MFD_PM8921_CORE tristate Qualcomm PM8921 PMIC chip depends on (ARCH_MSM || HEXAGON) - depends on BROKEN select MFD_CORE select MFD_PM8XXX help diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c index 669f8f2..7964932 100644 --- a/drivers/mfd/pm8921-core.c +++ b/drivers/mfd/pm8921-core.c @@ -15,6 +15,7 @@ #include linux/kernel.h #include linux/interrupt.h +#include linux/irqchip/chained_irq.h #include linux/irq.h #include linux/module.h #include linux/platform_device.h @@ -174,6 +175,8 @@ static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc) u8 root; int i, ret, masters = 0; + chained_irq_enter(irq_chip, desc); + ret = pm8xxx_read_root_irq(chip, root); if (ret) { pr_err(Can't read root status ret=%d\n, ret); @@ -188,7 +191,7 @@ static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc) if (masters (1 i)) pm8xxx_irq_master_handler(chip, i); - irq_chip-irq_ack(desc-irq_data); + chained_irq_exit(irq_chip, desc); } static void pm8xxx_irq_mask_ack(struct irq_data *d) @@ -367,7 +370,7 @@ static struct pm_irq_chip *pm8xxx_irq_init(struct device *dev, irq_set_irq_type(devirq, pdata-irq_trigger_flag); irq_set_handler_data(devirq, chip); irq_set_chained_handler(devirq, pm8xxx_irq_handler); - set_irq_wake(devirq, 1); + irq_set_irq_wake(devirq, 1); return chip; } -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 7/7] devicetree: bindings: Document PM8921/8058 PMICs
PM8921 and PM8058 are PMICs found paired with MSM8960 and MSM8660 devices respectively. They contain subdevices such as keypads, RTC, regulators, clocks, etc. Cc: devicet...@vger.kernel.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- .../devicetree/bindings/mfd/qcom,pm8xxx.txt| 63 ++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt diff --git a/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt new file mode 100644 index 000..e3fe625 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt @@ -0,0 +1,63 @@ +Qualcomm PM8xxx PMIC multi-function devices + +PROPERTIES + +- compatible: + Usage: required + Value type: string + Definition: must be one of: + qcom,pm8058 + qcom,pm8921 + +- #address-cells: + Usage: required + Value type: u32 + Definition: must be 1 + +- #size-cells: + Usage: required + Value type: u32 + Definition: must be 0 + +- interrupts: + Usage: required + Value type: prop-encoded-array + Definition: specifies the interrupt that indicates a subdevice + has generated an interrupt (summary interrupt). The + format of the specifier is defined by the binding document + describing the node's interrupt parent. + +- #interrupt-cells: + Usage: required + Value type : u32 + Definition: must be 2. Specifies the number of cells needed to encode + an interrupt source. The 1st cell contains the interrupt + number. The 2nd cell is the trigger type and level flags + encoded as follows: + + 1 = low-to-high edge triggered + 2 = high-to-low edge triggered + 4 = active high level-sensitive + 8 = active low level-sensitive + +- interrupt-controller: + Usage: required + Value type: empty + Definition: identifies this node as an interrupt controller + +EXAMPLE + + pmicintc: pmic@0 { + compatible = qcom,pm8921; + interrupts = 104 8; + #interrupt-cells = 2; + interrupt-controller; + #address-cells = 1; + #size-cells = 0; + + pwrkey { + compatible = qcom,pm8921-pwrkey; + interrupt-parent = pmicintc; + interrupts = 50 1, 51 1; + }; + }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/7] Modernize pm8921 with irqdomains, regmap, DT
These patches lay the groundwork for converting the pm8921 sub-devices to devicetree as well as simplify the API by migrating the core code to use the regmap API instead of the custom pm8xxx read/write wrapper. Changes since v1: * First 3 cleanup patches dropped because they're applied upstream * New regmap read/write helpers * New patch for DT match table * New binding document Stephen Boyd (7): mfd: Move pm8xxx-irq.c contents into only driver that uses it mfd: pm8921: Update for genirq changes mfd: pm8921: Migrate to irqdomains mfd: ssbi: Add regmap read/write helpers mfd: pm8921: Use ssbi regmap mfd: pm8921: Add DT match table devicetree: bindings: Document PM8921/8058 PMICs .../devicetree/bindings/mfd/qcom,pm8xxx.txt| 63 +++ drivers/mfd/Kconfig| 12 +- drivers/mfd/pm8921-core.c | 424 ++--- drivers/mfd/pm8xxx-irq.c | 371 -- drivers/mfd/ssbi.c | 13 + include/linux/mfd/pm8xxx/irq.h | 59 --- include/linux/mfd/pm8xxx/pm8921.h | 30 -- include/linux/ssbi.h | 3 + 8 files changed, 449 insertions(+), 526 deletions(-) create mode 100644 Documentation/devicetree/bindings/mfd/qcom,pm8xxx.txt delete mode 100644 drivers/mfd/pm8xxx-irq.c delete mode 100644 include/linux/mfd/pm8xxx/irq.h delete mode 100644 include/linux/mfd/pm8xxx/pm8921.h -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/9] CPU enable method based SMP/hotplug + MSM conversion
This is a rework of patches sent a months back by Rohit[1]. The goal of these patches is to add support for SMP and (basic) hotplug on MSM based SoCs. To get there, we add support for a generic way to hook in SMP/hotplug support code based on DT. To show how it's used, we convert the MSM8660 SMP support code over to the new method. After that we add support for the rest of the upstream MSM SoCs (note these patches are piled high on top of Rohit's patches to add 8074 support to MSM[2] and my follow ups[3,4], but this should only matter to the MSM maintainers). This is one of the last items of code that still requires us to have a mach directory and a machine descriptor. We should be able to move the hotplug/smp code out of mach directories if this approach is accepted. Changes since v1: * Added pointers from cpu nodes to saw and acc nodes * Squashed nr_cpus removal into reorganization patch * Reworked bindings/documentation * Rebased onto v3.13-rc4 [1] https://lkml.org/lkml/2013/8/1/770 [2] https://lkml.org/lkml/2013/10/17/520 [3] https://lkml.org/lkml/2013/10/18/406 [4] http://lkml.org/lkml/2013/10/28/501 Rohit Vaswani (6): devicetree: bindings: Document Krait/Scorpion cpus and enable-method ARM: msm: Remove pen_release usage ARM: msm: Re-organize platsmp to make it extensible ARM: msm: Add SMP support for KPSSv1 ARM: msm: Add SMP support for KPSSv2 ARM: dts: msm: Add nodes necessary for SMP boot Stephen Boyd (3): devicetree: bindings: Document qcom,kpss-acc devicetree: bindings: Document qcom,saw2 node ARM: Introduce CPU_METHOD_OF_DECLARE() for cpu hotplug/smp Documentation/devicetree/bindings/arm/cpus.txt | 25 +- .../devicetree/bindings/arm/msm/qcom,kpss-acc.txt | 30 ++ .../devicetree/bindings/arm/msm/qcom,saw2.txt | 35 ++ arch/arm/boot/dts/qcom-msm8660-surf.dts| 24 ++ arch/arm/boot/dts/qcom-msm8960-cdp.dts | 52 +++ arch/arm/boot/dts/qcom-msm8974.dtsi| 69 arch/arm/include/asm/smp.h | 9 + arch/arm/kernel/devtree.c | 40 +++ arch/arm/mach-msm/Makefile | 2 +- arch/arm/mach-msm/board-dt.c | 14 - arch/arm/mach-msm/common.h | 1 - arch/arm/mach-msm/headsmp.S| 39 --- arch/arm/mach-msm/hotplug.c| 31 +- arch/arm/mach-msm/platsmp.c| 371 - arch/arm/mach-msm/scm-boot.h | 8 +- include/asm-generic/vmlinux.lds.h | 10 + 16 files changed, 595 insertions(+), 165 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt delete mode 100644 arch/arm/mach-msm/headsmp.S -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 9/9] ARM: dts: msm: Add nodes necessary for SMP boot
From: Rohit Vaswani rvasw...@codeaurora.org Add the necessary nodes to support SMP on MSM8660, MSM8960, and MSM8974/APQ8074. While we're here also add in the error interrupts for the Krait cache error detection. Signed-off-by: Rohit Vaswani rvasw...@codeaurora.org [sboyd: Split into separate patch, add error interrupts] Signed-off-by: Stephen Boyd sb...@codeaurora.org --- arch/arm/boot/dts/qcom-msm8660-surf.dts | 24 arch/arm/boot/dts/qcom-msm8960-cdp.dts | 52 + arch/arm/boot/dts/qcom-msm8974.dtsi | 69 + 3 files changed, 145 insertions(+) diff --git a/arch/arm/boot/dts/qcom-msm8660-surf.dts b/arch/arm/boot/dts/qcom-msm8660-surf.dts index 20cb9ad..c72325e 100644 --- a/arch/arm/boot/dts/qcom-msm8660-surf.dts +++ b/arch/arm/boot/dts/qcom-msm8660-surf.dts @@ -9,6 +9,30 @@ compatible = qcom,msm8660-surf, qcom,msm8660; interrupt-parent = intc; + cpus { + #address-cells = 1; + #size-cells = 0; + compatible = qcom,scorpion; + enable-method = qcom,gcc-msm8660; + + cpu@0 { + device_type = cpu; + reg = 0; + next-level-cache = L2; + }; + + cpu@1 { + device_type = cpu; + reg = 1; + next-level-cache = L2; + }; + + L2: l2-cache { + compatible = cache; + cache-level = 2; + }; + }; + intc: interrupt-controller@208 { compatible = qcom,msm-8660-qgic; interrupt-controller; diff --git a/arch/arm/boot/dts/qcom-msm8960-cdp.dts b/arch/arm/boot/dts/qcom-msm8960-cdp.dts index d5b1318..bb20f94 100644 --- a/arch/arm/boot/dts/qcom-msm8960-cdp.dts +++ b/arch/arm/boot/dts/qcom-msm8960-cdp.dts @@ -9,6 +9,36 @@ compatible = qcom,msm8960-cdp, qcom,msm8960; interrupt-parent = intc; + cpus { + #address-cells = 1; + #size-cells = 0; + interrupts = 1 14 0x304; + compatible = qcom,krait; + enable-method = qcom,kpss-acc-v1; + + cpu@0 { + device_type = cpu; + reg = 0; + next-level-cache = L2; + qcom,acc = acc0; + qcom,saw = saw0; + }; + + cpu@1 { + device_type = cpu; + reg = 1; + next-level-cache = L2; + qcom,acc = acc1; + qcom,saw = saw1; + }; + + L2: l2-cache { + compatible = cache; + cache-level = 2; + interrupts = 0 2 0x4; + }; + }; + intc: interrupt-controller@200 { compatible = qcom,msm-qgic2; interrupt-controller; @@ -53,6 +83,28 @@ #reset-cells = 1; }; + acc0: clock-controller@2088000 { + compatible = qcom,kpss-acc-v1; + reg = 0x02088000 0x1000, 0x02008000 0x1000; + }; + + acc1: clock-controller@2098000 { + compatible = qcom,kpss-acc-v1; + reg = 0x02098000 0x1000, 0x02008000 0x1000; + }; + + saw0: regulator@2089000 { + compatible = qcom,saw2; + reg = 0x02089000 0x1000, 0x02009000 0x1000; + regulator; + }; + + saw1: regulator@2099000 { + compatible = qcom,saw2; + reg = 0x02099000 0x1000, 0x02009000 0x1000; + regulator; + }; + serial@1644 { compatible = qcom,msm-uartdm-v1.3, qcom,msm-uartdm; reg = 0x1644 0x1000, diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi index 9fa57d7..22555f6 100644 --- a/arch/arm/boot/dts/qcom-msm8974.dtsi +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi @@ -9,6 +9,49 @@ compatible = qcom,msm8974; interrupt-parent = intc; + cpus { + #address-cells = 1; + #size-cells = 0; + interrupts = 1 9 0xf04; + compatible = qcom,krait; + enable-method = qcom,kpss-acc-v2; + + cpu@0 { + device_type = cpu; + reg = 0; + next-level-cache = L2; + qcom,acc = acc0; + }; + + cpu@1 { + device_type = cpu; + reg = 1; + next-level-cache = L2; + qcom,acc = acc1; + }; + + cpu@2 { + device_type = cpu; + reg = 2;
[PATCH v2 3/9] devicetree: bindings: Document qcom,saw2 node
The saw2 binding describes the SPM/AVS wrapper hardware used to control the regulator supplying voltage to the Krait CPUs. Cc: devicet...@vger.kernel.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- .../devicetree/bindings/arm/msm/qcom,saw2.txt | 35 ++ 1 file changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt b/Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt new file mode 100644 index 000..1505fb8 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt @@ -0,0 +1,35 @@ +SPM AVS Wrapper 2 (SAW2) + +The SAW2 is a wrapper around the Subsystem Power Manager (SPM) and the +Adaptive Voltage Scaling (AVS) hardware. The SPM is a programmable +micro-controller that transitions a piece of hardware (like a processor or +subsystem) into and out of low power modes via a direct connection to +the PMIC. It can also be wired up to interact with other processors in the +system, notifying them when a low power state is entered or exited. + +PROPERTIES + +- compatible: + Usage: required + Value type: string + Definition: shall contain qcom,saw2. A more specific value should be + one of: +qcom,saw2-v1 +qcom,saw2-v1.1 +qcom,saw2-v2 +qcom,saw2-v2.1 + +- reg: + Usage: required + Value type: prop-encoded-array + Definition: the first element specifies the base address and size of + the register region. An optional second element specifies + the base address and size of the alias register region. + + +Example: + + regulator@2099000 { + compatible = qcom,saw2; + reg = 0x02099000 0x1000, 0x02009000 0x1000; + }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 8/9] ARM: msm: Add SMP support for KPSSv2
From: Rohit Vaswani rvasw...@codeaurora.org Implement support for the Krait CPU release sequence when the CPUs are part of the second version of the Krait processor subsystem. Signed-off-by: Rohit Vaswani rvasw...@codeaurora.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- arch/arm/mach-msm/platsmp.c | 123 1 file changed, 123 insertions(+) diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 4b13cd8..f07ad9d 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -38,7 +38,15 @@ #define L2DT_SLP BIT(3) #define CLAMP BIT(0) +#define APC_PWR_GATE_CTL 0x14 +#define BHS_CNT_SHIFT 24 +#define LDO_PWR_DWN_SHIFT 16 +#define LDO_BYP_SHIFT 8 +#define BHS_SEG_SHIFT 1 +#define BHS_EN BIT(0) + #define APCS_SAW2_VCTL 0x14 +#define APCS_SAW2_2_VCTL 0x1c extern void secondary_startup(void); @@ -157,6 +165,106 @@ out_acc: return ret; } +static int kpssv2_release_secondary(unsigned int cpu) +{ + void __iomem *reg; + struct device_node *cpu_node, *l2_node, *acc_node, *saw_node; + void __iomem *l2_saw_base; + unsigned reg_val; + int ret; + + cpu_node = of_get_cpu_node(cpu, NULL); + if (!cpu_node) + return -ENODEV; + + acc_node = of_parse_phandle(cpu_node, qcom,acc, 0); + if (!acc_node) { + ret = -ENODEV; + goto out_acc; + } + + l2_node = of_parse_phandle(cpu_node, next-level-cache, 0); + if (!l2_node) { + ret = -ENODEV; + goto out_l2; + } + + saw_node = of_parse_phandle(l2_node, qcom,saw, 0); + if (!saw_node) { + ret = -ENODEV; + goto out_saw; + } + + reg = of_iomap(acc_node, 0); + if (!reg) { + ret = -ENOMEM; + goto out_map; + } + + l2_saw_base = of_iomap(saw_node, 0); + if (!l2_saw_base) { + ret = -ENOMEM; + goto out_saw_map; + } + + /* Turn on the BHS, turn off LDO Bypass and power down LDO */ + reg_val = (64 BHS_CNT_SHIFT) | (0x3f LDO_PWR_DWN_SHIFT) | BHS_EN; + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); + mb(); + /* wait for the BHS to settle */ + udelay(1); + + /* Turn on BHS segments */ + reg_val |= 0x3f BHS_SEG_SHIFT; + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); + mb(); +/* wait for the BHS to settle */ + udelay(1); + + /* Finally turn on the bypass so that BHS supplies power */ + reg_val |= 0x3f LDO_BYP_SHIFT; + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); + + /* enable max phases */ + writel_relaxed(0x10003, l2_saw_base + APCS_SAW2_2_VCTL); + mb(); + udelay(50); + + reg_val = COREPOR_RST | CLAMP; + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); + mb(); + udelay(2); + + reg_val = ~CLAMP; + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); + mb(); + udelay(2); + + reg_val = ~COREPOR_RST; + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); + mb(); + + reg_val |= CORE_PWRD_UP; + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); + mb(); + + ret = 0; + + iounmap(l2_saw_base); +out_saw_map: + iounmap(reg); +out_map: + of_node_put(saw_node); +out_saw: + of_node_put(l2_node); +out_l2: + of_node_put(acc_node); +out_acc: + of_node_put(cpu_node); + + return ret; +} + static DEFINE_PER_CPU(int, cold_boot_done); static int msm_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) @@ -201,6 +309,11 @@ static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle) return msm_boot_secondary(cpu, kpssv1_release_secondary); } +static int kpssv2_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + return msm_boot_secondary(cpu, kpssv2_release_secondary); +} + static void __init msm_smp_prepare_cpus(unsigned int max_cpus) { int cpu, map; @@ -250,3 +363,13 @@ static struct smp_operations msm_smp_kpssv1_ops __initdata = { #endif }; CPU_METHOD_OF_DECLARE(msm_smp_kpssv1, qcom,kpss-acc-v1, msm_smp_kpssv1_ops); + +static struct smp_operations msm_smp_kpssv2_ops __initdata = { + .smp_prepare_cpus = msm_smp_prepare_cpus, + .smp_secondary_init = msm_secondary_init, + .smp_boot_secondary = kpssv2_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die= msm_cpu_die, +#endif +}; +CPU_METHOD_OF_DECLARE(msm_smp_kpssv2, qcom,kpss-acc-v2, msm_smp_kpssv2_ops); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to
[PATCH v2 7/9] ARM: msm: Add SMP support for KPSSv1
From: Rohit Vaswani rvasw...@codeaurora.org Implement support for the Krait CPU release sequence when the CPUs are part of the first version of the krait processor subsystem. Signed-off-by: Rohit Vaswani rvasw...@codeaurora.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- arch/arm/mach-msm/platsmp.c | 106 +++ arch/arm/mach-msm/scm-boot.h | 8 ++-- 2 files changed, 111 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 11c6239..4b13cd8 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -30,6 +30,16 @@ #define SCSS_CPU1CORE_RESET0x2d80 #define SCSS_DBG_STATUS_CORE_PWRDUP0x2e64 +#define APCS_CPU_PWR_CTL 0x04 +#define PLL_CLAMP BIT(8) +#define CORE_PWRD_UP BIT(7) +#define COREPOR_RSTBIT(5) +#define CORE_RST BIT(4) +#define L2DT_SLP BIT(3) +#define CLAMP BIT(0) + +#define APCS_SAW2_VCTL 0x14 + extern void secondary_startup(void); static DEFINE_SPINLOCK(boot_lock); @@ -68,6 +78,85 @@ static int scss_release_secondary(unsigned int cpu) return 0; } +static int kpssv1_release_secondary(unsigned int cpu) +{ + int ret = 0; + void __iomem *reg, *saw_reg; + struct device_node *cpu_node, *acc_node, *saw_node; + u32 val; + + cpu_node = of_get_cpu_node(cpu, NULL); + if (!cpu_node) + return -ENODEV; + + acc_node = of_parse_phandle(cpu_node, qcom,acc, 0); + if (!acc_node) { + ret = -ENODEV; + goto out_acc; + } + + saw_node = of_parse_phandle(cpu_node, qcom,saw, 0); + if (!saw_node) { + ret = -ENODEV; + goto out_saw; + } + + reg = of_iomap(acc_node, 0); + if (!reg) { + ret = -ENOMEM; + goto out_acc_map; + } + + saw_reg = of_iomap(saw_node, 0); + if (!saw_reg) { + ret = -ENOMEM; + goto out_saw_map; + } + + /* Turn on CPU rail */ + writel_relaxed(0xA4, saw_reg + APCS_SAW2_VCTL); + mb(); + udelay(512); + + /* Krait bring-up sequence */ + val = PLL_CLAMP | L2DT_SLP | CLAMP; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + val = ~L2DT_SLP; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + mb(); + ndelay(300); + + val |= COREPOR_RST; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + mb(); + udelay(2); + + val = ~CLAMP; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + mb(); + udelay(2); + + val = ~COREPOR_RST; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + mb(); + udelay(100); + + val |= CORE_PWRD_UP; + writel_relaxed(val, reg + APCS_CPU_PWR_CTL); + mb(); + + iounmap(saw_reg); +out_saw_map: + iounmap(reg); +out_acc_map: + of_node_put(saw_node); +out_saw: + of_node_put(acc_node); +out_acc: + of_node_put(cpu_node); + return ret; +} + static DEFINE_PER_CPU(int, cold_boot_done); static int msm_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) @@ -107,6 +196,11 @@ static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle) return msm_boot_secondary(cpu, scss_release_secondary); } +static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + return msm_boot_secondary(cpu, kpssv1_release_secondary); +} + static void __init msm_smp_prepare_cpus(unsigned int max_cpus) { int cpu, map; @@ -114,6 +208,8 @@ static void __init msm_smp_prepare_cpus(unsigned int max_cpus) static const int cold_boot_flags[] = { 0, SCM_FLAG_COLDBOOT_CPU1, + SCM_FLAG_COLDBOOT_CPU2, + SCM_FLAG_COLDBOOT_CPU3, }; for_each_present_cpu(cpu) { @@ -144,3 +240,13 @@ static struct smp_operations msm_smp_8660_ops __initdata = { #endif }; CPU_METHOD_OF_DECLARE(msm_smp, qcom,gcc-msm8660, msm_smp_8660_ops); + +static struct smp_operations msm_smp_kpssv1_ops __initdata = { + .smp_prepare_cpus = msm_smp_prepare_cpus, + .smp_secondary_init = msm_secondary_init, + .smp_boot_secondary = kpssv1_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die= msm_cpu_die, +#endif +}; +CPU_METHOD_OF_DECLARE(msm_smp_kpssv1, qcom,kpss-acc-v1, msm_smp_kpssv1_ops); diff --git a/arch/arm/mach-msm/scm-boot.h b/arch/arm/mach-msm/scm-boot.h index 7be32ff..6aabb24 100644 --- a/arch/arm/mach-msm/scm-boot.h +++ b/arch/arm/mach-msm/scm-boot.h @@ -13,9 +13,11 @@ #define __MACH_SCM_BOOT_H #define SCM_BOOT_ADDR 0x1 -#define SCM_FLAG_COLDBOOT_CPU1 0x1 -#define SCM_FLAG_WARMBOOT_CPU1 0x2 -#define SCM_FLAG_WARMBOOT_CPU0 0x4 +#define SCM_FLAG_COLDBOOT_CPU1 0x01
[PATCH v2 6/9] ARM: msm: Re-organize platsmp to make it extensible
From: Rohit Vaswani rvasw...@codeaurora.org This makes it easy to add SMP support for new devices by keying on a device node for the release sequence. We add the enable-method property for the cpus property to specify that we want to use the gcc-msm8660 release sequence (which is going to look for the global clock controller device node to map some Scorpion specific power and control registers). We also remove the nr_cpus detection code as that is done generically in the DT CPU detection code. Signed-off-by: Rohit Vaswani rvasw...@codeaurora.org [sboyd: Port to CPU_METHOD_OF_DECLARE] Signed-off-by: Stephen Boyd sb...@codeaurora.org --- arch/arm/mach-msm/board-dt.c | 14 -- arch/arm/mach-msm/common.h | 1 - arch/arm/mach-msm/platsmp.c | 117 --- 3 files changed, 65 insertions(+), 67 deletions(-) diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c index 1f11d93..1e3af2b 100644 --- a/arch/arm/mach-msm/board-dt.c +++ b/arch/arm/mach-msm/board-dt.c @@ -11,31 +11,17 @@ */ #include linux/init.h -#include linux/of.h -#include linux/of_platform.h #include asm/mach/arch.h -#include asm/mach/map.h - -#include common.h static const char * const msm_dt_match[] __initconst = { qcom,msm8660-fluid, qcom,msm8660-surf, qcom,msm8960-cdp, - NULL -}; - -static const char * const apq8074_dt_match[] __initconst = { qcom,apq8074-dragonboard, NULL }; DT_MACHINE_START(MSM_DT, Qualcomm MSM (Flattened Device Tree)) - .smp = smp_ops(msm_smp_ops), .dt_compat = msm_dt_match, MACHINE_END - -DT_MACHINE_START(APQ_DT, Qualcomm MSM (Flattened Device Tree)) - .dt_compat = apq8074_dt_match, -MACHINE_END diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h index 33c7725..1513f2c 100644 --- a/arch/arm/mach-msm/common.h +++ b/arch/arm/mach-msm/common.h @@ -23,7 +23,6 @@ extern void msm_map_qsd8x50_io(void); extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size, unsigned int mtype, void *caller); -extern struct smp_operations msm_smp_ops; extern void msm_cpu_die(unsigned int cpu); struct msm_mmc_platform_data; diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 5b481db..11c6239 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -13,6 +13,8 @@ #include linux/delay.h #include linux/device.h #include linux/jiffies.h +#include linux/of.h +#include linux/of_address.h #include linux/smp.h #include linux/io.h @@ -24,20 +26,14 @@ #include scm-boot.h #include common.h -#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0 -#define SCSS_CPU1CORE_RESET 0xD80 -#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64 +#define VDD_SC1_ARRAY_CLAMP_GFS_CTL0x35a0 +#define SCSS_CPU1CORE_RESET0x2d80 +#define SCSS_DBG_STATUS_CORE_PWRDUP0x2e64 extern void secondary_startup(void); static DEFINE_SPINLOCK(boot_lock); -static inline int get_core_count(void) -{ - /* 1 + the PART[1:0] field of MIDR */ - return ((read_cpuid_id() 4) 3) + 1; -} - static void msm_secondary_init(unsigned int cpu) { /* @@ -47,33 +43,41 @@ static void msm_secondary_init(unsigned int cpu) spin_unlock(boot_lock); } -static void prepare_cold_cpu(unsigned int cpu) +static int scss_release_secondary(unsigned int cpu) { - int ret; - ret = scm_set_boot_addr(virt_to_phys(secondary_startup), - SCM_FLAG_COLDBOOT_CPU1); - if (ret == 0) { - void __iomem *sc1_base_ptr; - sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2); - if (sc1_base_ptr) { - writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL); - writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET); - writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP); - iounmap(sc1_base_ptr); - } - } else - printk(KERN_DEBUG Failed to set secondary core boot - address\n); + struct device_node *node; + void __iomem *base; + + node = of_find_compatible_node(NULL, NULL, qcom,gcc-msm8660); + if (!node) { + pr_err(%s: can't find node\n, __func__); + return -ENXIO; + } + + base = of_iomap(node, 0); + of_node_put(node); + if (!base) + return -ENOMEM; + + writel_relaxed(0, base + VDD_SC1_ARRAY_CLAMP_GFS_CTL); + writel_relaxed(0, base + SCSS_CPU1CORE_RESET); + writel_relaxed(3, base + SCSS_DBG_STATUS_CORE_PWRDUP); + mb(); + iounmap(base); + + return 0; } -static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle) +static DEFINE_PER_CPU(int, cold_boot_done); + +static int msm_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) { - static int
[PATCH v2 2/9] devicetree: bindings: Document qcom,kpss-acc
The kpss acc binding describes the clock, reset, and power domain controller for a Krait CPU. Cc: devicet...@vger.kernel.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- .../devicetree/bindings/arm/msm/qcom,kpss-acc.txt | 30 ++ 1 file changed, 30 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt new file mode 100644 index 000..1333db9 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt @@ -0,0 +1,30 @@ +Krait Processor Sub-system (KPSS) Application Clock Controller (ACC) + +The KPSS ACC provides clock, power domain, and reset control to a Krait CPU. +There is one ACC register region per CPU within the KPSS remapped region as +well as an alias register region that remaps accesses to the ACC associated +with the CPU accessing the region. + +PROPERTIES + +- compatible: + Usage: required + Value type: string + Definition: should be one of: + qcom,kpss-acc-v1 + qcom,kpss-acc-v2 + +- reg: + Usage: required + Value type: prop-encoded-array + Definition: the first element specifies the base address and size of + the register region. An optional second element specifies + the base address and size of the alias register region. + +Example: + + clock-controller@2088000 { + compatible = qcom,kpss-acc-v2; + reg = 0x02088000 0x1000, + 0x02008000 0x1000; + }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 5/9] ARM: msm: Remove pen_release usage
From: Rohit Vaswani rvasw...@codeaurora.org pen_release is no longer required as the synchronization is now managed by generic arm code. This is done as suggested in https://lkml.org/lkml/2013/6/4/184 Cc: Russell King li...@arm.linux.org.uk Signed-off-by: Rohit Vaswani rvasw...@codeaurora.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- arch/arm/mach-msm/Makefile | 2 +- arch/arm/mach-msm/headsmp.S | 39 --- arch/arm/mach-msm/hotplug.c | 31 --- arch/arm/mach-msm/platsmp.c | 35 +++ 4 files changed, 8 insertions(+), 99 deletions(-) delete mode 100644 arch/arm/mach-msm/headsmp.S diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 7ed4c1b..15562cf 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -19,7 +19,7 @@ obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -obj-$(CONFIG_SMP) += headsmp.o platsmp.o +obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o diff --git a/arch/arm/mach-msm/headsmp.S b/arch/arm/mach-msm/headsmp.S deleted file mode 100644 index 6c62c3f..000 --- a/arch/arm/mach-msm/headsmp.S +++ /dev/null @@ -1,39 +0,0 @@ -/* - * linux/arch/arm/mach-realview/headsmp.S - * - * Copyright (c) 2003 ARM Limited - * 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 as - * published by the Free Software Foundation. - */ -#include linux/linkage.h -#include linux/init.h - -/* - * MSM specific entry point for secondary CPUs. This provides - * a holding pen into which all secondary cores are held until we're - * ready for them to initialise. - */ -ENTRY(msm_secondary_startup) - mrc p15, 0, r0, c0, c0, 5 - and r0, r0, #15 - adr r4, 1f - ldmia r4, {r5, r6} - sub r4, r4, r5 - add r6, r6, r4 -pen: ldr r7, [r6] - cmp r7, r0 - bne pen - - /* -* we've been released from the holding pen: secondary_stack -* should now contain the SVC stack for this core -*/ - b secondary_startup -ENDPROC(msm_secondary_startup) - - .align -1: .long . - .long pen_release diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c index 326a872..cea80fc 100644 --- a/arch/arm/mach-msm/hotplug.c +++ b/arch/arm/mach-msm/hotplug.c @@ -24,33 +24,10 @@ static inline void cpu_leave_lowpower(void) static inline void platform_do_lowpower(unsigned int cpu) { - /* Just enter wfi for now. TODO: Properly shut off the cpu. */ - for (;;) { - /* -* here's the WFI -*/ - asm(wfi - : - : - : memory, cc); - - if (pen_release == cpu_logical_map(cpu)) { - /* -* OK, proper wakeup, we're done -*/ - break; - } - - /* -* getting here, means that we have come out of WFI without -* having been woken up - this shouldn't happen -* -* The trouble is, letting people know about this is not really -* possible, since we are currently running incoherently, and -* therefore cannot safely call printk() or anything else -*/ - pr_debug(CPU%u: spurious wakeup call\n, cpu); - } + asm(wfi + : + : + : memory, cc); } /* diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 3f06edc..5b481db 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -28,7 +28,7 @@ #define SCSS_CPU1CORE_RESET 0xD80 #define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64 -extern void msm_secondary_startup(void); +extern void secondary_startup(void); static DEFINE_SPINLOCK(boot_lock); @@ -41,13 +41,6 @@ static inline int get_core_count(void) static void msm_secondary_init(unsigned int cpu) { /* -* let the primary processor know we're out of the -* pen, then head off into the C entry point -*/ - pen_release = -1; - smp_wmb(); - - /* * Synchronise with the boot thread. */ spin_lock(boot_lock); @@ -57,7 +50,7 @@ static void msm_secondary_init(unsigned int cpu) static void prepare_cold_cpu(unsigned int cpu) { int ret; - ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup), + ret =
[PATCH v2 4/9] ARM: Introduce CPU_METHOD_OF_DECLARE() for cpu hotplug/smp
The goal of multi-platform kernels is to remove the need for mach directories and machine descriptors. To further that goal, introduce CPU_METHOD_OF_DECLARE() to allow cpu hotplug/smp support to be separated from the machine descriptors. Implementers should specify an enable-method property in their cpus node and then implement a matching set of smp_ops in their hotplug/smp code, wiring it up with the CPU_METHOD_OF_DECLARE() macro. When the kernel is compiled we'll collect all the enable-method smp_ops into one section for use at boot. At boot time we'll look for an enable-method in each cpu node and try to match that against all known CPU enable methods in the kernel. If there are no enable-methods in the cpu nodes we fallback to the cpus node and try to use any enable-method found there. If that doesn't work we fall back to the old way of using the machine descriptor. Cc: Mark Rutland mark.rutl...@arm.com Cc: Russell King li...@arm.linux.org.uk Cc: devicet...@vger.kernel.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- arch/arm/include/asm/smp.h| 9 + arch/arm/kernel/devtree.c | 40 +++ include/asm-generic/vmlinux.lds.h | 10 ++ 3 files changed, 59 insertions(+) diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 22a3b9b..772435b 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -114,6 +114,15 @@ struct smp_operations { #endif }; +struct of_cpu_method { + const char *method; + struct smp_operations *ops; +}; + +#define CPU_METHOD_OF_DECLARE(name, _method, _ops) \ + static const struct of_cpu_method __cpu_method_of_table_##name \ + __used __section(__cpu_method_of_table) \ + = { .method = _method, .ops = _ops } /* * set platform specific SMP operations */ diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index 739c3df..91cc3f8 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -18,6 +18,7 @@ #include linux/of_fdt.h #include linux/of_irq.h #include linux/of_platform.h +#include linux/smp.h #include asm/cputype.h #include asm/setup.h @@ -63,6 +64,34 @@ void __init arm_dt_memblock_reserve(void) } } +#ifdef CONFIG_SMP +extern struct of_cpu_method __cpu_method_of_table_begin[]; +extern struct of_cpu_method __cpu_method_of_table_end[]; + +static int __init set_smp_ops_by_method(struct device_node *node) +{ + const char *method; + struct of_cpu_method *m = __cpu_method_of_table_begin; + + if (of_property_read_string(node, enable-method, method)) + return 0; + + for (; m __cpu_method_of_table_end; m++) + if (!strcmp(m-method, method)) { + smp_set_ops(m-ops); + return 1; + } + + return 0; +} +#else +static inline int set_smp_ops_by_method(struct device_node *node) +{ + return 1; +} +#endif + + /* * arm_dt_init_cpu_maps - Function retrieves cpu nodes from the device tree * and builds the cpu logical map array containing MPIDR values related to @@ -79,6 +108,7 @@ void __init arm_dt_init_cpu_maps(void) * read as 0. */ struct device_node *cpu, *cpus; + int found_method = 0; u32 i, j, cpuidx = 1; u32 mpidr = is_smp() ? read_cpuid_mpidr() MPIDR_HWID_BITMASK : 0; @@ -150,8 +180,18 @@ void __init arm_dt_init_cpu_maps(void) } tmp_map[i] = hwid; + + if (!found_method) + found_method = set_smp_ops_by_method(cpu); } + /* +* Fallback to an enable-method in the cpus node if nothing found in +* a cpu node. +*/ + if (!found_method) + set_smp_ops_by_method(cpus); + if (!bootcpu_valid) { pr_warn(DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map\n); return; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index bc2121f..bd02ca7 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -167,6 +167,15 @@ #define CLK_OF_TABLES() #endif +#ifdef CONFIG_SMP +#define CPU_METHOD_OF_TABLES() . = ALIGN(8); \ + VMLINUX_SYMBOL(__cpu_method_of_table_begin) = .; \ + *(__cpu_method_of_table) \ + VMLINUX_SYMBOL(__cpu_method_of_table_end) = .; +#else +#define CPU_METHOD_OF_TABLES() +#endif + #define KERNEL_DTB() \ STRUCT_ALIGN(); \ VMLINUX_SYMBOL(__dtb_start) = .;\ @@ -491,6 +500,7 @@ MEM_DISCARD(init.rodata)\
[PATCH v2 1/9] devicetree: bindings: Document Krait/Scorpion cpus and enable-method
From: Rohit Vaswani rvasw...@codeaurora.org Scorpion and Krait don't use the spin-table enable-method. Instead they rely on mmio register accesses to enable power and clocks to bring CPUs out of reset. Document their enable-methods. Cc: devicet...@vger.kernel.org Signed-off-by: Rohit Vaswani rvasw...@codeaurora.org [sboyd: Split off into separate patch, renamed methods to match compatible nodes] Signed-off-by: Stephen Boyd sb...@codeaurora.org --- Documentation/devicetree/bindings/arm/cpus.txt | 25 - 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index 9130435..333f4ae 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt @@ -180,7 +180,11 @@ nodes to be present and contain the properties described below. be one of: spin-table psci - # On ARM 32-bit systems this property is optional. + # On ARM 32-bit systems this property is optional and + can be one of: + qcom,gcc-msm8660 + qcom,kpss-acc-v1 + qcom,kpss-acc-v2 - cpu-release-addr Usage: required for systems that have an enable-method @@ -191,6 +195,21 @@ nodes to be present and contain the properties described below. property identifying a 64-bit zero-initialised memory location. + - qcom,saw + Usage: required for systems that have an enable-method + property value of qcom,kpss-acc-v1 or + qcom,kpss-acc-v2 + Value type: phandle + Definition: Specifies the SAW[1] node associated with this CPU. + + - qcom,acc + Usage: required for systems that have an enable-method + property value of qcom,kpss-acc-v1 or + qcom,kpss-acc-v2 + Value type: phandle + Definition: Specifies the ACC[2] node associated with this CPU. + + Example 1 (dual-cluster big.LITTLE system 32-bit): cpus { @@ -382,3 +401,7 @@ cpus { cpu-release-addr = 0 0x2000; }; }; + +-- +[1] arm/msm/qcom,saw2.txt +[2] arm/msm/qcom,kpss-acc.txt -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 00/15] Add support for MSM's mmio clock/reset controller
The first breaks a reset-controller include ordering requirement. I hope it can go through the clock tree. The next 3 patches are generic clock framework patches. They add support for regmap and for setting the rate and the parent at the same time based on patches from James Hogan's remuxing set_rate series. After that we add MSM clock hardware support and SoC specific drivers. The DT node additions will be sent through the MSM maintainers once these patches are accepted. Changes since v3: * Moved binding include to clock/ * New patch for 8660 GCC driver * Renamed directory to qcom to match vendor prefix * Added some missing clocks in 8974 GCC driver * New patch for 8974 MMCC driver Changes since v2: * Completed 8960 and 8974 GCC data dt-bindings * Added support for reset controllers * Squashed some bugs in 8974 gcc clocks * New patch to fix clk NULL pointer deref * New patch to fix #include requirement for reset-controller.h Changes since v1: * Rewrote binding to use #clock-cells=1 * Reworked library components (pll, rcg, branch) to use regmap * Dropped common clock framework patches that did DT parsing * New patches for regmap support in common clock framework Stephen Boyd (15): reset: Silence warning in reset-controller.h clk: Allow drivers to pass in a regmap clk: Add regmap core helpers for enable/disable/is_enabled clk: Add set_rate_and_parent() op clk: qcom: Add support for phase locked loops (PLLs) clk: qcom: Add support for root clock generators (RCGs) clk: qcom: Add support for branches/gate clocks clk: qcom: Add reset controller support clk: qcom: Add support for MSM8960's global clock controller (GCC) clk: qcom: Add support for MSM8960's multimedia clock controller (MMCC) clk: qcom: Add support for MSM8974's global clock controller (GCC) clk: qcom: Add support for MSM8974's multimedia clock controller (MMCC) clk: qcom: Add support for MSM8660's global clock controller (GCC) devicetree: bindings: Document qcom,gcc devicetree: bindings: Document qcom,mmcc Documentation/clk.txt |3 + .../devicetree/bindings/clock/qcom,gcc.txt | 21 + .../devicetree/bindings/clock/qcom,mmcc.txt| 21 + drivers/clk/Kconfig|2 + drivers/clk/Makefile |1 + drivers/clk/clk.c | 156 +- drivers/clk/qcom/Kconfig | 47 + drivers/clk/qcom/Makefile | 13 + drivers/clk/qcom/clk-branch.c | 159 ++ drivers/clk/qcom/clk-branch.h | 53 + drivers/clk/qcom/clk-pll.c | 222 ++ drivers/clk/qcom/clk-pll.h | 65 + drivers/clk/qcom/clk-rcg.c | 517 drivers/clk/qcom/clk-rcg.h | 157 + drivers/clk/qcom/clk-rcg2.c| 291 ++ drivers/clk/qcom/gcc-msm8660.c | 2818 ++ drivers/clk/qcom/gcc-msm8960.c | 2992 drivers/clk/qcom/gcc-msm8974.c | 2693 ++ drivers/clk/qcom/mmcc-msm8960.c| 2320 +++ drivers/clk/qcom/mmcc-msm8974.c| 2624 + drivers/clk/qcom/reset.c | 63 + drivers/clk/qcom/reset.h | 37 + include/dt-bindings/clock/qcom,gcc-msm8660.h | 276 ++ include/dt-bindings/clock/qcom,gcc-msm8960.h | 313 ++ include/dt-bindings/clock/qcom,gcc-msm8974.h | 320 +++ include/dt-bindings/clock/qcom,mmcc-msm8960.h | 137 + include/dt-bindings/clock/qcom,mmcc-msm8974.h | 161 ++ include/dt-bindings/reset/qcom,gcc-msm8660.h | 134 + include/dt-bindings/reset/qcom,gcc-msm8960.h | 118 + include/dt-bindings/reset/qcom,gcc-msm8974.h | 96 + include/dt-bindings/reset/qcom,mmcc-msm8960.h | 93 + include/dt-bindings/reset/qcom,mmcc-msm8974.h | 62 + include/linux/clk-provider.h | 35 + include/linux/reset-controller.h |1 + 34 files changed, 17002 insertions(+), 19 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc.txt create mode 100644 Documentation/devicetree/bindings/clock/qcom,mmcc.txt create mode 100644 drivers/clk/qcom/Kconfig create mode 100644 drivers/clk/qcom/Makefile create mode 100644 drivers/clk/qcom/clk-branch.c create mode 100644 drivers/clk/qcom/clk-branch.h create mode 100644 drivers/clk/qcom/clk-pll.c create mode 100644 drivers/clk/qcom/clk-pll.h create mode 100644 drivers/clk/qcom/clk-rcg.c create mode 100644 drivers/clk/qcom/clk-rcg.h create mode 100644 drivers/clk/qcom/clk-rcg2.c create mode 100644 drivers/clk/qcom/gcc-msm8660.c create mode 100644 drivers/clk/qcom/gcc-msm8960.c create mode 100644
[PATCH v4 15/15] devicetree: bindings: Document qcom,mmcc
Document the multimedia clock controller found on MSM devices Cc: devicet...@vger.kernel.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- .../devicetree/bindings/clock/qcom,mmcc.txt | 21 + 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,mmcc.txt diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.txt b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt new file mode 100644 index 000..d572e99 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt @@ -0,0 +1,21 @@ +Qualcomm Multimedia Clock Reset Controller Binding + + +Required properties : +- compatible : shall contain only one of the following: + + qcom,mmcc-msm8660 + qcom,mmcc-msm8960 + qcom,mmcc-msm8974 + +- reg : shall contain base register location and length +- #clock-cells : shall contain 1 +- #reset-cells : shall contain 1 + +Example: + clock-controller@400 { + compatible = qcom,mmcc-msm8960; + reg = 0x400 0x1000; + #clock-cells = 1; + #reset-cells = 1; + }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 14/15] devicetree: bindings: Document qcom,gcc
Document the global clock controller found on MSM devices. Cc: devicet...@vger.kernel.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- .../devicetree/bindings/clock/qcom,gcc.txt | 21 + 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc.txt diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt new file mode 100644 index 000..767401f --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt @@ -0,0 +1,21 @@ +Qualcomm Global Clock Reset Controller Binding + + +Required properties : +- compatible : shall contain only one of the following: + + qcom,gcc-msm8660 + qcom,gcc-msm8960 + qcom,gcc-msm8974 + +- reg : shall contain base register location and length +- #clock-cells : shall contain 1 +- #reset-cells : shall contain 1 + +Example: + clock-controller@90 { + compatible = qcom,gcc-msm8960; + reg = 0x90 0x4000; + #clock-cells = 1; + #reset-cells = 1; + }; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 06/15] clk: qcom: Add support for root clock generators (RCGs)
Add support for the root clock generators on Qualcomm devices. RCGs are highly customizable mux/divider/counter clocks that can be used to generate almost any rate desired given some input source that is faster than the desired rate. Signed-off-by: Stephen Boyd sb...@codeaurora.org --- drivers/clk/qcom/Makefile | 2 + drivers/clk/qcom/clk-rcg.c | 517 drivers/clk/qcom/clk-rcg.h | 157 ++ drivers/clk/qcom/clk-rcg2.c | 291 + 4 files changed, 967 insertions(+) create mode 100644 drivers/clk/qcom/clk-rcg.c create mode 100644 drivers/clk/qcom/clk-rcg.h create mode 100644 drivers/clk/qcom/clk-rcg2.c diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 9849a99..7ed16d7 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -1,3 +1,5 @@ obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-pll.o +clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg.o +clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg2.o diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c new file mode 100644 index 000..afc0401 --- /dev/null +++ b/drivers/clk/qcom/clk-rcg.c @@ -0,0 +1,517 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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/kernel.h +#include linux/bitops.h +#include linux/err.h +#include linux/export.h +#include linux/clk-provider.h +#include linux/regmap.h + +#include asm/div64.h + +#include clk-rcg.h + +static u32 ns_to_src(struct src_sel *s, u32 ns) +{ + ns = s-src_sel_shift; + ns = SRC_SEL_MASK; + return ns; +} + +static u32 src_to_ns(struct src_sel *s, u8 src, u32 ns) +{ + u32 mask; + + mask = SRC_SEL_MASK; + mask = s-src_sel_shift; + ns = ~mask; + + ns |= src s-src_sel_shift; + return ns; +} + +static u8 clk_rcg_get_parent(struct clk_hw *hw) +{ + struct clk_rcg *rcg = to_clk_rcg(hw); + int num_parents = __clk_get_num_parents(hw-clk); + u32 ns; + int i; + + regmap_read(hw-regmap, rcg-ns_reg, ns); + ns = ns_to_src(rcg-s, ns); + for (i = 0; i num_parents; i++) + if (ns == rcg-s.parent_map[i]) + return i; + + return -EINVAL; +} + +static int reg_to_bank(struct clk_dyn_rcg *rcg, u32 bank) +{ + bank = BIT(rcg-mux_sel_bit); + return !!bank; +} + +static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw) +{ + struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); + int num_parents = __clk_get_num_parents(hw-clk); + u32 ns, ctl; + int bank; + int i; + struct src_sel *s; + + regmap_read(hw-regmap, hw-enable_reg, ctl); + bank = reg_to_bank(rcg, ctl); + s = rcg-s[bank]; + + regmap_read(hw-regmap, rcg-ns_reg, ns); + ns = ns_to_src(s, ns); + + for (i = 0; i num_parents; i++) + if (ns == s-parent_map[i]) + return i; + + return -EINVAL; +} + +static int clk_rcg_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_rcg *rcg = to_clk_rcg(hw); + u32 ns; + + regmap_read(hw-regmap, rcg-ns_reg, ns); + ns = src_to_ns(rcg-s, rcg-s.parent_map[index], ns); + regmap_write(hw-regmap, rcg-ns_reg, ns); + + return 0; +} + +static u32 md_to_m(struct mn *mn, u32 md) +{ + md = mn-m_val_shift; + md = BIT(mn-width) - 1; + return md; +} + +static u32 ns_to_pre_div(struct pre_div *p, u32 ns) +{ + ns = p-pre_div_shift; + ns = BIT(p-pre_div_width) - 1; + return ns; +} + +static u32 pre_div_to_ns(struct pre_div *p, u8 pre_div, u32 ns) +{ + u32 mask; + + mask = BIT(p-pre_div_width) - 1; + mask = p-pre_div_shift; + ns = ~mask; + + ns |= pre_div p-pre_div_shift; + return ns; +} + +static u32 mn_to_md(struct mn *mn, u32 m, u32 n, u32 md) +{ + u32 mask, mask_w; + + mask_w = BIT(mn-width) - 1; + mask = (mask_w mn-m_val_shift) | mask_w; + md = ~mask; + + if (n) { + m = mn-m_val_shift; + md |= m; + md |= ~n mask_w; + } + + return md; +} + +static u32 ns_m_to_n(struct mn *mn, u32 ns, u32 m) +{ + ns = ~ns mn-n_val_shift; + ns = BIT(mn-width) - 1; + return ns + m; +} + +static u32 reg_to_mnctr_mode(struct mn *mn, u32 val) +{ + val = mn-mnctr_mode_shift; + val = MNCTR_MODE_MASK; + return val; +} + +static u32
[PATCH v4 01/15] reset: Silence warning in reset-controller.h
If a user of linux/reset-controller.h doesn't include linux/of.h before including reset-controller.h they'll get a warning as follows: include/linux/reset-controller.h:44:17: warning: 'struct of_phandle_args' declared inside parameter list This is because of_phandle_args is not forward declared. Add the declaration to silence this warning. Cc: Philipp Zabel p.za...@pengutronix.de Signed-off-by: Stephen Boyd sb...@codeaurora.org --- include/linux/reset-controller.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h index 2f61311..41a4695 100644 --- a/include/linux/reset-controller.h +++ b/include/linux/reset-controller.h @@ -21,6 +21,7 @@ struct reset_control_ops { struct module; struct device_node; +struct of_phandle_args; /** * struct reset_controller_dev - reset controller entity that might -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 08/15] clk: qcom: Add reset controller support
Reset controllers and clock controllers are combined into one IP block on Qualcomm chipsets. Usually a reset signal is associated with each clock branch but sometimes a reset signal is associated with a handful of clocks. Either way the register interface is the same; set a bit to assert a reset and clear a bit to deassert a reset. Add support for these types of resets signals. Signed-off-by: Stephen Boyd sb...@codeaurora.org --- drivers/clk/qcom/Kconfig | 2 +- drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/reset.c | 63 +++ drivers/clk/qcom/reset.h | 37 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/qcom/reset.c create mode 100644 drivers/clk/qcom/reset.h diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 73a8c8f..06ccce6 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -2,4 +2,4 @@ config COMMON_CLK_QCOM tristate Support for Qualcomm's clock controllers depends on OF select REGMAP_MMIO - + select RESET_CONTROLLER diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 58a5ab3..b2568be 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -4,3 +4,4 @@ clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-pll.o clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg.o clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg2.o clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-branch.o +clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += reset.o diff --git a/drivers/clk/qcom/reset.c b/drivers/clk/qcom/reset.c new file mode 100644 index 000..6c977d3 --- /dev/null +++ b/drivers/clk/qcom/reset.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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/bitops.h +#include linux/export.h +#include linux/regmap.h +#include linux/reset-controller.h +#include linux/delay.h + +#include reset.h + +static int qcom_reset(struct reset_controller_dev *rcdev, unsigned long id) +{ + rcdev-ops-assert(rcdev, id); + udelay(1); + rcdev-ops-deassert(rcdev, id); + return 0; +} + +static int +qcom_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) +{ + struct qcom_reset_controller *rst; + const struct qcom_reset_map *map; + u32 mask; + + rst = to_qcom_reset_controller(rcdev); + map = rst-reset_map[id]; + mask = BIT(map-bit); + + return regmap_update_bits(rst-regmap, map-reg, mask, mask); +} + +static int +qcom_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) +{ + struct qcom_reset_controller *rst; + const struct qcom_reset_map *map; + u32 mask; + + rst = to_qcom_reset_controller(rcdev); + map = rst-reset_map[id]; + mask = BIT(map-bit); + + return regmap_update_bits(rst-regmap, map-reg, mask, 0); +} + +struct reset_control_ops qcom_reset_ops = { + .reset = qcom_reset, + .assert = qcom_reset_assert, + .deassert = qcom_reset_deassert, +}; +EXPORT_SYMBOL_GPL(qcom_reset_ops); diff --git a/drivers/clk/qcom/reset.h b/drivers/clk/qcom/reset.h new file mode 100644 index 000..e22b167 --- /dev/null +++ b/drivers/clk/qcom/reset.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef __MSM_CLK_RESET_H__ +#define __MSM_CLK_RESET_H__ + +#include linux/reset-controller.h + +struct qcom_reset_map { + unsigned int reg; + u8 bit; +}; + +struct regmap; + +struct qcom_reset_controller { + const struct qcom_reset_map *reset_map; + struct regmap *regmap; + struct reset_controller_dev rcdev; +}; + +#define to_qcom_reset_controller(r) \ + container_of(r, struct qcom_reset_controller, rcdev); + +extern struct reset_control_ops qcom_reset_ops; + +#endif -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message
[PATCH v4 02/15] clk: Allow drivers to pass in a regmap
Add support to the clock core so that drivers can pass in a regmap. If no regmap is specified try to query the device that's registering the clock for its regmap. This should allow drivers to use the core regmap helpers. This is based on a similar design in the regulator framework. Cc: Mark Brown broo...@kernel.org Signed-off-by: Stephen Boyd sb...@codeaurora.org --- drivers/clk/clk.c| 8 include/linux/clk-provider.h | 7 +++ 2 files changed, 15 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 9ad7b71..5e71f5c 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -20,6 +20,7 @@ #include linux/device.h #include linux/init.h #include linux/sched.h +#include linux/regmap.h static DEFINE_SPINLOCK(enable_lock); static DEFINE_MUTEX(prepare_lock); @@ -1834,6 +1835,13 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) clk-num_parents = hw-init-num_parents; hw-clk = clk; + if (hw-init-regmap) + hw-regmap = hw-init-regmap; + else if (dev dev_get_regmap(dev, NULL)) + hw-regmap = dev_get_regmap(dev, NULL); + else if (dev dev-parent) + hw-regmap = dev_get_regmap(dev-parent, NULL); + /* allocate local copy in case parent_names is __initdata */ clk-parent_names = kcalloc(clk-num_parents, sizeof(char *), GFP_KERNEL); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 7e59253..31f2890 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -142,6 +142,8 @@ struct clk_ops { void(*init)(struct clk_hw *hw); }; +struct regmap; + /** * struct clk_init_data - holds init data that's common to all clocks and is * shared between the clock provider and the common clock framework. @@ -151,6 +153,7 @@ struct clk_ops { * @parent_names: array of string names for all possible parents * @num_parents: number of possible parents * @flags: framework-level hints and quirks + * @regmap: regmap to use for regmap helpers and/or by providers */ struct clk_init_data { const char *name; @@ -158,6 +161,7 @@ struct clk_init_data { const char **parent_names; u8 num_parents; unsigned long flags; + struct regmap *regmap; }; /** @@ -171,10 +175,13 @@ struct clk_init_data { * * @init: pointer to struct clk_init_data that contains the init data shared * with the common clock framework. + * + * @regmap: regmap to use for regmap helpers and/or by providers */ struct clk_hw { struct clk *clk; const struct clk_init_data *init; + struct regmap *regmap; }; /* -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line unsubscribe linux-arm-msm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 05/15] clk: qcom: Add support for phase locked loops (PLLs)
Add support for Qualcomm's PLLs (phase locked loops). This is sufficient enough to be able to determine the rate the PLL is running at. We can add rate setting support later when it's needed. Signed-off-by: Stephen Boyd sb...@codeaurora.org --- drivers/clk/Kconfig| 2 + drivers/clk/Makefile | 1 + drivers/clk/qcom/Kconfig | 5 + drivers/clk/qcom/Makefile | 3 + drivers/clk/qcom/clk-pll.c | 222 + drivers/clk/qcom/clk-pll.h | 65 + 6 files changed, 298 insertions(+) create mode 100644 drivers/clk/qcom/Kconfig create mode 100644 drivers/clk/qcom/Makefile create mode 100644 drivers/clk/qcom/clk-pll.c create mode 100644 drivers/clk/qcom/clk-pll.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 5c51115..afd2a45 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -107,6 +107,8 @@ config COMMON_CLK_KEYSTONE Supports clock drivers for Keystone based SOCs. These SOCs have local a power sleep control module that gate the clock to the IPs and PLLs. +source drivers/clk/qcom/Kconfig + endmenu source drivers/clk/mvebu/Kconfig diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 7a10bc9..088b517 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-$(CONFIG_ARCH_U300)+= clk-u300.o obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/ obj-$(CONFIG_ARCH_SIRF)+= clk-prima2.o +obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ obj-$(CONFIG_PLAT_ORION) += mvebu/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_ARCH_MMP) += mmp/ diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig new file mode 100644 index 000..73a8c8f --- /dev/null +++ b/drivers/clk/qcom/Kconfig @@ -0,0 +1,5 @@ +config COMMON_CLK_QCOM + tristate Support for Qualcomm's clock controllers + depends on OF + select REGMAP_MMIO + diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile new file mode 100644 index 000..9849a99 --- /dev/null +++ b/drivers/clk/qcom/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o + +clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-pll.o diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c new file mode 100644 index 000..b0d2a4e --- /dev/null +++ b/drivers/clk/qcom/clk-pll.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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/kernel.h +#include linux/bitops.h +#include linux/err.h +#include linux/bug.h +#include linux/delay.h +#include linux/export.h +#include linux/clk-provider.h +#include linux/regmap.h + +#include asm/div64.h + +#include clk-pll.h + +#define PLL_OUTCTRLBIT(0) +#define PLL_BYPASSNL BIT(1) +#define PLL_RESET_NBIT(2) +#define PLL_LOCK_COUNT_SHIFT 8 +#define PLL_LOCK_COUNT_MASK0x3f +#define PLL_BIAS_COUNT_SHIFT 14 +#define PLL_BIAS_COUNT_MASK0x3f +#define PLL_VOTE_FSM_ENA BIT(20) +#define PLL_VOTE_FSM_RESET BIT(21) + +static int clk_pll_enable(struct clk_hw *hw) +{ + struct clk_pll *pll = to_clk_pll(hw); + int ret; + u32 mask, val; + + mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL; + ret = regmap_read(hw-regmap, pll-mode_reg, val); + if (ret) + return ret; + + /* Skip if already enabled or in FSM mode */ + if ((val mask) == mask || val PLL_VOTE_FSM_ENA) + return 0; + + /* Disable PLL bypass mode. */ + ret = regmap_update_bits(hw-regmap, pll-mode_reg, PLL_BYPASSNL, +PLL_BYPASSNL); + if (ret) + return ret; + + /* +* H/W requires a 5us delay between disabling the bypass and +* de-asserting the reset. Delay 10us just to be safe. +*/ + udelay(10); + + /* De-assert active-low PLL reset. */ + ret = regmap_update_bits(hw-regmap, pll-mode_reg, PLL_RESET_N, +PLL_RESET_N); + if (ret) + return ret; + + /* Wait until PLL is locked. */ + udelay(50); + + /* Enable PLL output. */ + ret = regmap_update_bits(hw-regmap, pll-mode_reg, PLL_OUTCTRL, +PLL_OUTCTRL); + if (ret) + return ret; + + return 0; +} + +static void clk_pll_disable(struct clk_hw *hw) +{ + struct clk_pll *pll = to_clk_pll(hw); + u32 mask; +
[PATCH v4 04/15] clk: Add set_rate_and_parent() op
Some of Qualcomm's clocks can change their parent and rate at the same time with a single register write. Add support for this hardware to the common clock framework by adding a new set_rate_and_parent() op. When the clock framework determines that both the parent and the rate are going to change during clk_set_rate() it will call the .set_rate_and_parent() op if available and fall back to calling .set_parent() followed by .set_rate() otherwise. Reviewed-by: James Hogan james.ho...@imgtec.com Signed-off-by: Stephen Boyd sb...@codeaurora.org --- Documentation/clk.txt| 3 ++ drivers/clk/clk.c| 78 +--- include/linux/clk-provider.h | 15 + 3 files changed, 77 insertions(+), 19 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 3aeb5c4..79700ea 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -77,6 +77,9 @@ the operations defined in clk.h: int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long); + int (*set_rate_and_parent)(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate, u8 index); void(*init)(struct clk_hw *hw); }; diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 8b40170..e33abeb 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1200,10 +1200,9 @@ static void clk_reparent(struct clk *clk, struct clk *new_parent) clk-parent = new_parent; } -static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) +static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent) { unsigned long flags; - int ret = 0; struct clk *old_parent = clk-parent; /* @@ -1234,6 +1233,34 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) clk_reparent(clk, parent); clk_enable_unlock(flags); + return old_parent; +} + +static void __clk_set_parent_after(struct clk *clk, struct clk *parent, + struct clk *old_parent) +{ + /* +* Finish the migration of prepare state and undo the changes done +* for preventing a race with clk_enable(). +*/ + if (clk-prepare_count) { + clk_disable(clk); + clk_disable(old_parent); + __clk_unprepare(old_parent); + } + + /* update debugfs with new clk tree topology */ + clk_debug_reparent(clk, parent); +} + +static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) +{ + unsigned long flags; + int ret = 0; + struct clk *old_parent; + + old_parent = __clk_set_parent_before(clk, parent); + /* change clock input source */ if (parent clk-ops-set_parent) ret = clk-ops-set_parent(clk-hw, p_index); @@ -1251,18 +1278,8 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) return ret; } - /* -* Finish the migration of prepare state and undo the changes done -* for preventing a race with clk_enable(). -*/ - if (clk-prepare_count) { - clk_disable(clk); - clk_disable(old_parent); - __clk_unprepare(old_parent); - } + __clk_set_parent_after(clk, parent, old_parent); - /* update debugfs with new clk tree topology */ - clk_debug_reparent(clk, parent); return 0; } @@ -1447,17 +1464,32 @@ static void clk_change_rate(struct clk *clk) struct clk *child; unsigned long old_rate; unsigned long best_parent_rate = 0; + bool skip_set_rate = false; + struct clk *old_parent; old_rate = clk-rate; - /* set parent */ - if (clk-new_parent clk-new_parent != clk-parent) - __clk_set_parent(clk, clk-new_parent, clk-new_parent_index); - - if (clk-parent) + if (clk-new_parent) + best_parent_rate = clk-new_parent-rate; + else if (clk-parent) best_parent_rate = clk-parent-rate; - if (clk-ops-set_rate) + if (clk-new_parent clk-new_parent != clk-parent) { + old_parent = __clk_set_parent_before(clk, clk-new_parent); + + if (clk-ops-set_rate_and_parent) { + skip_set_rate = true; + clk-ops-set_rate_and_parent(clk-hw, clk-new_rate, + best_parent_rate, + clk-new_parent_index); + } else if (clk-ops-set_parent) { + clk-ops-set_parent(clk-hw, clk-new_parent_index); + } + +
Re: [PATCH v4 1/1] usb: gadget: f_fs: Add support for SuperSpeed Mode
On Mon, Dec 23 2013, Manu Gautam mgau...@codeaurora.org wrote: Allow userspace to pass SuperSpeed descriptors and handle them in the driver accordingly. This change doesn't modify existing desc_header and thereby keeps the ABI changes backward compatible i.e. existing userspace drivers compiled with old header (functionfs.h) would continue to work with the updated kernel. I'm mostly fine with this patch. If you change __ffs_func_bind_do_descs as I've described inline, feel free to resend with: Acked-by: Michal Nazarewicz min...@mina86.com The other two minor issues are up to you. I don't have strong feelings. Signed-off-by: Manu Gautam mgau...@codeaurora.org --- drivers/usb/gadget/f_fs.c | 176 +++--- drivers/usb/gadget/u_fs.h | 8 ++- 2 files changed, 142 insertions(+), 42 deletions(-) diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 306a2b5..8c7bf04 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1607,22 +1630,58 @@ static int __ffs_data_got_descs(struct ffs_data *ffs, } if (likely(hs_count)) { - ret = ffs_do_descs(hs_count, data, len, + hs_len = ffs_do_descs(hs_count, data, len, __ffs_data_do_entity, ffs); - if (unlikely(ret 0)) + if (unlikely(hs_len 0)) { + ret = hs_len; + goto error; + } + + data += hs_len; + len -= hs_len; + } else { + hs_len = 0; + } + + if (len = 8) { + /* Check SS_MAGIC for presence of ss_descs and get SS_COUNT */ + if (get_unaligned_le32(data) != FUNCTIONFS_SS_DESC_MAGIC) + goto einval; + + ss_count = get_unaligned_le32(data + 4); + data += 8; + len -= 8; + } + + if (!fs_count !hs_count !ss_count) + goto einval; + + if (ss_count) { + ss_len = ffs_do_descs(ss_count, data, len, +__ffs_data_do_entity, ffs); + if (unlikely(ss_len 0)) { + ret = ss_len; goto error; + } + ret = ss_len; } else { + ss_len = 0; ret = 0; } if (unlikely(len != ret)) goto einval; - ffs-raw_fs_descs_length = fs_len; - ffs-raw_descs_length= fs_len + ret; - ffs-raw_descs = _data; - ffs-fs_descs_count = fs_count; - ffs-hs_descs_count = hs_count; + ffs-raw_fs_hs_descs_length = fs_len + hs_len; + ffs-raw_ss_descs_length = ss_len; + ffs-raw_descs_length= fs_len + hs_len + ss_len; This can always be calculated as the sum of the other two fields, so perhaps the redundancy in the structure is not needed, especially as this is only used in _ffs_func_bind? + ffs-raw_descs = _data; + ffs-fs_descs_count = fs_count; + ffs-hs_descs_count = hs_count; + ffs-ss_descs_count = ss_count; + /* ss_descs? present @ header + hs_fs_descs + ss_magic + ss_count */ + if (ffs-ss_descs_count) + ffs-raw_ss_descs_offset = 16 + ffs-raw_fs_hs_descs_length + 8; Similarly here, the offset is easily calculated from the other fields. I don't have strong feelings, but perhaps it would end up being cleaner if the values were calculated on demand in _ffs_func_bind? return 0; @@ -1850,16 +1909,23 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, * If hs_descriptors is not NULL then we are reading hs * descriptors now */ - const int isHS = func-function.hs_descriptors != NULL; - unsigned idx; + const int is_hs = func-function.hs_descriptors != NULL; + const int is_ss = func-function.ss_descriptors != NULL; + unsigned ep_desc_id, idx; if (type != FFS_DESCRIPTOR) return 0; - if (isHS) + if (is_ss) { + func-function.ss_descriptors[(long)valuep] = desc; + ep_desc_id = 2; + } else if (is_hs) { func-function.hs_descriptors[(long)valuep] = desc; - else + ep_desc_id = 1; + } else { func-function.fs_descriptors[(long)valuep]= desc; + ep_desc_id = 0; + } I should have caught it in my previous review. Since is_hs and is_ss are mutually exclusive, it would be better to use ep_desc_id as a single 3-state variable than having two 2-state variables, which may cause some confusion as to what they actually mean. So how about: unsigned ed_desc_id, idx; if (type != FFS_DESCRIPTOR) return 0; /* * If ss_descriptors is not NULL, we are reading super