0001
0002
0003
0004
0005
0006 #include <linux/clk.h>
0007 #include <linux/interrupt.h>
0008 #include <linux/irqchip/chained_irq.h>
0009 #include <linux/irqdesc.h>
0010 #include <linux/irqdomain.h>
0011 #include <linux/irq.h>
0012 #include <linux/mfd/imx25-tsadc.h>
0013 #include <linux/module.h>
0014 #include <linux/of.h>
0015 #include <linux/of_platform.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/regmap.h>
0018
0019 static struct regmap_config mx25_tsadc_regmap_config = {
0020 .fast_io = true,
0021 .max_register = 8,
0022 .reg_bits = 32,
0023 .val_bits = 32,
0024 .reg_stride = 4,
0025 };
0026
0027 static void mx25_tsadc_irq_handler(struct irq_desc *desc)
0028 {
0029 struct mx25_tsadc *tsadc = irq_desc_get_handler_data(desc);
0030 struct irq_chip *chip = irq_desc_get_chip(desc);
0031 u32 status;
0032
0033 chained_irq_enter(chip, desc);
0034
0035 regmap_read(tsadc->regs, MX25_TSC_TGSR, &status);
0036
0037 if (status & MX25_TGSR_GCQ_INT)
0038 generic_handle_domain_irq(tsadc->domain, 1);
0039
0040 if (status & MX25_TGSR_TCQ_INT)
0041 generic_handle_domain_irq(tsadc->domain, 0);
0042
0043 chained_irq_exit(chip, desc);
0044 }
0045
0046 static int mx25_tsadc_domain_map(struct irq_domain *d, unsigned int irq,
0047 irq_hw_number_t hwirq)
0048 {
0049 struct mx25_tsadc *tsadc = d->host_data;
0050
0051 irq_set_chip_data(irq, tsadc);
0052 irq_set_chip_and_handler(irq, &dummy_irq_chip,
0053 handle_level_irq);
0054 irq_modify_status(irq, IRQ_NOREQUEST, IRQ_NOPROBE);
0055
0056 return 0;
0057 }
0058
0059 static const struct irq_domain_ops mx25_tsadc_domain_ops = {
0060 .map = mx25_tsadc_domain_map,
0061 .xlate = irq_domain_xlate_onecell,
0062 };
0063
0064 static int mx25_tsadc_setup_irq(struct platform_device *pdev,
0065 struct mx25_tsadc *tsadc)
0066 {
0067 struct device *dev = &pdev->dev;
0068 struct device_node *np = dev->of_node;
0069 int irq;
0070
0071 irq = platform_get_irq(pdev, 0);
0072 if (irq <= 0)
0073 return irq;
0074
0075 tsadc->domain = irq_domain_add_simple(np, 2, 0, &mx25_tsadc_domain_ops,
0076 tsadc);
0077 if (!tsadc->domain) {
0078 dev_err(dev, "Failed to add irq domain\n");
0079 return -ENOMEM;
0080 }
0081
0082 irq_set_chained_handler_and_data(irq, mx25_tsadc_irq_handler, tsadc);
0083
0084 return 0;
0085 }
0086
0087 static void mx25_tsadc_setup_clk(struct platform_device *pdev,
0088 struct mx25_tsadc *tsadc)
0089 {
0090 unsigned clk_div;
0091
0092
0093
0094
0095
0096
0097
0098
0099 dev_dbg(&pdev->dev, "Found master clock at %lu Hz\n",
0100 clk_get_rate(tsadc->clk));
0101
0102 clk_div = DIV_ROUND_UP(clk_get_rate(tsadc->clk), 1750000);
0103 dev_dbg(&pdev->dev, "Setting up ADC clock divider to %u\n", clk_div);
0104
0105
0106 clk_div -= 2;
0107 clk_div /= 2;
0108
0109
0110
0111
0112
0113 clk_div = max_t(unsigned, 4, clk_div);
0114
0115 dev_dbg(&pdev->dev, "Resulting ADC conversion clock at %lu Hz\n",
0116 clk_get_rate(tsadc->clk) / (2 * clk_div + 2));
0117
0118 regmap_update_bits(tsadc->regs, MX25_TSC_TGCR,
0119 MX25_TGCR_ADCCLKCFG(0x1f),
0120 MX25_TGCR_ADCCLKCFG(clk_div));
0121 }
0122
0123 static int mx25_tsadc_probe(struct platform_device *pdev)
0124 {
0125 struct device *dev = &pdev->dev;
0126 struct mx25_tsadc *tsadc;
0127 struct resource *res;
0128 int ret;
0129 void __iomem *iomem;
0130
0131 tsadc = devm_kzalloc(dev, sizeof(*tsadc), GFP_KERNEL);
0132 if (!tsadc)
0133 return -ENOMEM;
0134
0135 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0136 iomem = devm_ioremap_resource(dev, res);
0137 if (IS_ERR(iomem))
0138 return PTR_ERR(iomem);
0139
0140 tsadc->regs = devm_regmap_init_mmio(dev, iomem,
0141 &mx25_tsadc_regmap_config);
0142 if (IS_ERR(tsadc->regs)) {
0143 dev_err(dev, "Failed to initialize regmap\n");
0144 return PTR_ERR(tsadc->regs);
0145 }
0146
0147 tsadc->clk = devm_clk_get(dev, "ipg");
0148 if (IS_ERR(tsadc->clk)) {
0149 dev_err(dev, "Failed to get ipg clock\n");
0150 return PTR_ERR(tsadc->clk);
0151 }
0152
0153
0154 mx25_tsadc_setup_clk(pdev, tsadc);
0155
0156
0157 regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_CLK_EN,
0158 MX25_TGCR_CLK_EN);
0159 regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_TSC_RST,
0160 MX25_TGCR_TSC_RST);
0161
0162
0163 regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_POWERMODE_MASK,
0164 MX25_TGCR_POWERMODE_SAVE);
0165 regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_INTREFEN,
0166 MX25_TGCR_INTREFEN);
0167
0168 ret = mx25_tsadc_setup_irq(pdev, tsadc);
0169 if (ret)
0170 return ret;
0171
0172 platform_set_drvdata(pdev, tsadc);
0173
0174 return devm_of_platform_populate(dev);
0175 }
0176
0177 static int mx25_tsadc_remove(struct platform_device *pdev)
0178 {
0179 struct mx25_tsadc *tsadc = platform_get_drvdata(pdev);
0180 int irq = platform_get_irq(pdev, 0);
0181
0182 if (irq) {
0183 irq_set_chained_handler_and_data(irq, NULL, NULL);
0184 irq_domain_remove(tsadc->domain);
0185 }
0186
0187 return 0;
0188 }
0189
0190 static const struct of_device_id mx25_tsadc_ids[] = {
0191 { .compatible = "fsl,imx25-tsadc" },
0192 { }
0193 };
0194 MODULE_DEVICE_TABLE(of, mx25_tsadc_ids);
0195
0196 static struct platform_driver mx25_tsadc_driver = {
0197 .driver = {
0198 .name = "mx25-tsadc",
0199 .of_match_table = mx25_tsadc_ids,
0200 },
0201 .probe = mx25_tsadc_probe,
0202 .remove = mx25_tsadc_remove,
0203 };
0204 module_platform_driver(mx25_tsadc_driver);
0205
0206 MODULE_DESCRIPTION("MFD for ADC/TSC for Freescale mx25");
0207 MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>");
0208 MODULE_LICENSE("GPL v2");
0209 MODULE_ALIAS("platform:mx25-tsadc");