Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright 2005-2008 Freescale Semiconductor, Inc. All Rights Reserved.
0004  * Copyright 2008 Luotao Fu, kernel@pengutronix.de
0005  */
0006 
0007 #include <linux/clk.h>
0008 #include <linux/delay.h>
0009 #include <linux/io.h>
0010 #include <linux/ktime.h>
0011 #include <linux/module.h>
0012 #include <linux/mod_devicetable.h>
0013 #include <linux/platform_device.h>
0014 
0015 #include <linux/w1.h>
0016 
0017 /*
0018  * MXC W1 Register offsets
0019  */
0020 #define MXC_W1_CONTROL      0x00
0021 # define MXC_W1_CONTROL_RDST    BIT(3)
0022 # define MXC_W1_CONTROL_WR(x)   BIT(5 - (x))
0023 # define MXC_W1_CONTROL_PST BIT(6)
0024 # define MXC_W1_CONTROL_RPP BIT(7)
0025 #define MXC_W1_TIME_DIVIDER 0x02
0026 #define MXC_W1_RESET        0x04
0027 # define MXC_W1_RESET_RST   BIT(0)
0028 
0029 struct mxc_w1_device {
0030     void __iomem *regs;
0031     struct clk *clk;
0032     struct w1_bus_master bus_master;
0033 };
0034 
0035 /*
0036  * this is the low level routine to
0037  * reset the device on the One Wire interface
0038  * on the hardware
0039  */
0040 static u8 mxc_w1_ds2_reset_bus(void *data)
0041 {
0042     struct mxc_w1_device *dev = data;
0043     ktime_t timeout;
0044 
0045     writeb(MXC_W1_CONTROL_RPP, dev->regs + MXC_W1_CONTROL);
0046 
0047     /* Wait for reset sequence 511+512us, use 1500us for sure */
0048     timeout = ktime_add_us(ktime_get(), 1500);
0049 
0050     udelay(511 + 512);
0051 
0052     do {
0053         u8 ctrl = readb(dev->regs + MXC_W1_CONTROL);
0054 
0055         /* PST bit is valid after the RPP bit is self-cleared */
0056         if (!(ctrl & MXC_W1_CONTROL_RPP))
0057             return !(ctrl & MXC_W1_CONTROL_PST);
0058     } while (ktime_before(ktime_get(), timeout));
0059 
0060     return 1;
0061 }
0062 
0063 /*
0064  * this is the low level routine to read/write a bit on the One Wire
0065  * interface on the hardware. It does write 0 if parameter bit is set
0066  * to 0, otherwise a write 1/read.
0067  */
0068 static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit)
0069 {
0070     struct mxc_w1_device *dev = data;
0071     ktime_t timeout;
0072 
0073     writeb(MXC_W1_CONTROL_WR(bit), dev->regs + MXC_W1_CONTROL);
0074 
0075     /* Wait for read/write bit (60us, Max 120us), use 200us for sure */
0076     timeout = ktime_add_us(ktime_get(), 200);
0077 
0078     udelay(60);
0079 
0080     do {
0081         u8 ctrl = readb(dev->regs + MXC_W1_CONTROL);
0082 
0083         /* RDST bit is valid after the WR1/RD bit is self-cleared */
0084         if (!(ctrl & MXC_W1_CONTROL_WR(bit)))
0085             return !!(ctrl & MXC_W1_CONTROL_RDST);
0086     } while (ktime_before(ktime_get(), timeout));
0087 
0088     return 0;
0089 }
0090 
0091 static int mxc_w1_probe(struct platform_device *pdev)
0092 {
0093     struct mxc_w1_device *mdev;
0094     unsigned long clkrate;
0095     unsigned int clkdiv;
0096     int err;
0097 
0098     mdev = devm_kzalloc(&pdev->dev, sizeof(struct mxc_w1_device),
0099                 GFP_KERNEL);
0100     if (!mdev)
0101         return -ENOMEM;
0102 
0103     mdev->clk = devm_clk_get(&pdev->dev, NULL);
0104     if (IS_ERR(mdev->clk))
0105         return PTR_ERR(mdev->clk);
0106 
0107     err = clk_prepare_enable(mdev->clk);
0108     if (err)
0109         return err;
0110 
0111     clkrate = clk_get_rate(mdev->clk);
0112     if (clkrate < 10000000)
0113         dev_warn(&pdev->dev,
0114              "Low clock frequency causes improper function\n");
0115 
0116     clkdiv = DIV_ROUND_CLOSEST(clkrate, 1000000);
0117     clkrate /= clkdiv;
0118     if ((clkrate < 980000) || (clkrate > 1020000))
0119         dev_warn(&pdev->dev,
0120              "Incorrect time base frequency %lu Hz\n", clkrate);
0121 
0122     mdev->regs = devm_platform_ioremap_resource(pdev, 0);
0123     if (IS_ERR(mdev->regs)) {
0124         err = PTR_ERR(mdev->regs);
0125         goto out_disable_clk;
0126     }
0127 
0128     /* Software reset 1-Wire module */
0129     writeb(MXC_W1_RESET_RST, mdev->regs + MXC_W1_RESET);
0130     writeb(0, mdev->regs + MXC_W1_RESET);
0131 
0132     writeb(clkdiv - 1, mdev->regs + MXC_W1_TIME_DIVIDER);
0133 
0134     mdev->bus_master.data = mdev;
0135     mdev->bus_master.reset_bus = mxc_w1_ds2_reset_bus;
0136     mdev->bus_master.touch_bit = mxc_w1_ds2_touch_bit;
0137 
0138     platform_set_drvdata(pdev, mdev);
0139 
0140     err = w1_add_master_device(&mdev->bus_master);
0141     if (err)
0142         goto out_disable_clk;
0143 
0144     return 0;
0145 
0146 out_disable_clk:
0147     clk_disable_unprepare(mdev->clk);
0148     return err;
0149 }
0150 
0151 /*
0152  * disassociate the w1 device from the driver
0153  */
0154 static int mxc_w1_remove(struct platform_device *pdev)
0155 {
0156     struct mxc_w1_device *mdev = platform_get_drvdata(pdev);
0157 
0158     w1_remove_master_device(&mdev->bus_master);
0159 
0160     clk_disable_unprepare(mdev->clk);
0161 
0162     return 0;
0163 }
0164 
0165 static const struct of_device_id mxc_w1_dt_ids[] = {
0166     { .compatible = "fsl,imx21-owire" },
0167     { /* sentinel */ }
0168 };
0169 MODULE_DEVICE_TABLE(of, mxc_w1_dt_ids);
0170 
0171 static struct platform_driver mxc_w1_driver = {
0172     .driver = {
0173         .name = "mxc_w1",
0174         .of_match_table = mxc_w1_dt_ids,
0175     },
0176     .probe = mxc_w1_probe,
0177     .remove = mxc_w1_remove,
0178 };
0179 module_platform_driver(mxc_w1_driver);
0180 
0181 MODULE_LICENSE("GPL");
0182 MODULE_AUTHOR("Freescale Semiconductors Inc");
0183 MODULE_DESCRIPTION("Driver for One-Wire on MXC");