0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/ahci_platform.h>
0013 #include <linux/clk.h>
0014 #include <linux/errno.h>
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017 #include <linux/of_device.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/regulator/consumer.h>
0020 #include "ahci.h"
0021
0022 #define DRV_NAME "ahci-sunxi"
0023
0024
0025 static bool enable_pmp;
0026 module_param(enable_pmp, bool, 0);
0027 MODULE_PARM_DESC(enable_pmp,
0028 "Enable support for sata port multipliers, only use if you use a pmp!");
0029
0030 #define AHCI_BISTAFR 0x00a0
0031 #define AHCI_BISTCR 0x00a4
0032 #define AHCI_BISTFCTR 0x00a8
0033 #define AHCI_BISTSR 0x00ac
0034 #define AHCI_BISTDECR 0x00b0
0035 #define AHCI_DIAGNR0 0x00b4
0036 #define AHCI_DIAGNR1 0x00b8
0037 #define AHCI_OOBR 0x00bc
0038 #define AHCI_PHYCS0R 0x00c0
0039 #define AHCI_PHYCS1R 0x00c4
0040 #define AHCI_PHYCS2R 0x00c8
0041 #define AHCI_TIMER1MS 0x00e0
0042 #define AHCI_GPARAM1R 0x00e8
0043 #define AHCI_GPARAM2R 0x00ec
0044 #define AHCI_PPARAMR 0x00f0
0045 #define AHCI_TESTR 0x00f4
0046 #define AHCI_VERSIONR 0x00f8
0047 #define AHCI_IDR 0x00fc
0048 #define AHCI_RWCR 0x00fc
0049 #define AHCI_P0DMACR 0x0170
0050 #define AHCI_P0PHYCR 0x0178
0051 #define AHCI_P0PHYSR 0x017c
0052
0053 static void sunxi_clrbits(void __iomem *reg, u32 clr_val)
0054 {
0055 u32 reg_val;
0056
0057 reg_val = readl(reg);
0058 reg_val &= ~(clr_val);
0059 writel(reg_val, reg);
0060 }
0061
0062 static void sunxi_setbits(void __iomem *reg, u32 set_val)
0063 {
0064 u32 reg_val;
0065
0066 reg_val = readl(reg);
0067 reg_val |= set_val;
0068 writel(reg_val, reg);
0069 }
0070
0071 static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val)
0072 {
0073 u32 reg_val;
0074
0075 reg_val = readl(reg);
0076 reg_val &= ~(clr_val);
0077 reg_val |= set_val;
0078 writel(reg_val, reg);
0079 }
0080
0081 static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift)
0082 {
0083 return (readl(reg) >> shift) & mask;
0084 }
0085
0086 static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
0087 {
0088 u32 reg_val;
0089 int timeout;
0090
0091
0092 writel(0, reg_base + AHCI_RWCR);
0093 msleep(5);
0094
0095 sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
0096 sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
0097 (0x7 << 24),
0098 (0x5 << 24) | BIT(23) | BIT(18));
0099 sunxi_clrsetbits(reg_base + AHCI_PHYCS1R,
0100 (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
0101 (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
0102 sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
0103 sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19));
0104 sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
0105 (0x7 << 20), (0x3 << 20));
0106 sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
0107 (0x1f << 5), (0x19 << 5));
0108 msleep(5);
0109
0110 sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
0111
0112 timeout = 250;
0113 do {
0114 reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
0115 if (reg_val == 0x02)
0116 break;
0117
0118 if (--timeout == 0) {
0119 dev_err(dev, "PHY power up failed.\n");
0120 return -EIO;
0121 }
0122 udelay(1);
0123 } while (1);
0124
0125 sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24));
0126
0127 timeout = 100;
0128 do {
0129 reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
0130 if (reg_val == 0x00)
0131 break;
0132
0133 if (--timeout == 0) {
0134 dev_err(dev, "PHY calibration failed.\n");
0135 return -EIO;
0136 }
0137 udelay(1);
0138 } while (1);
0139
0140 msleep(15);
0141
0142 writel(0x7, reg_base + AHCI_RWCR);
0143
0144 return 0;
0145 }
0146
0147 static void ahci_sunxi_start_engine(struct ata_port *ap)
0148 {
0149 void __iomem *port_mmio = ahci_port_base(ap);
0150 struct ahci_host_priv *hpriv = ap->host->private_data;
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196 sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ffff, 0x00004433);
0197
0198
0199 sunxi_setbits(port_mmio + PORT_CMD, PORT_CMD_START);
0200 }
0201
0202 static const struct ata_port_info ahci_sunxi_port_info = {
0203 .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ | ATA_FLAG_NO_DIPM,
0204 .pio_mask = ATA_PIO4,
0205 .udma_mask = ATA_UDMA6,
0206 .port_ops = &ahci_platform_ops,
0207 };
0208
0209 static struct scsi_host_template ahci_platform_sht = {
0210 AHCI_SHT(DRV_NAME),
0211 };
0212
0213 static int ahci_sunxi_probe(struct platform_device *pdev)
0214 {
0215 struct device *dev = &pdev->dev;
0216 struct ahci_host_priv *hpriv;
0217 int rc;
0218
0219 hpriv = ahci_platform_get_resources(pdev, AHCI_PLATFORM_GET_RESETS);
0220 if (IS_ERR(hpriv))
0221 return PTR_ERR(hpriv);
0222
0223 hpriv->start_engine = ahci_sunxi_start_engine;
0224
0225 rc = ahci_platform_enable_resources(hpriv);
0226 if (rc)
0227 return rc;
0228
0229 rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
0230 if (rc)
0231 goto disable_resources;
0232
0233 hpriv->flags = AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
0234 AHCI_HFLAG_YES_NCQ;
0235
0236
0237
0238
0239
0240
0241 if (!enable_pmp)
0242 hpriv->flags |= AHCI_HFLAG_NO_PMP;
0243
0244 rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info,
0245 &ahci_platform_sht);
0246 if (rc)
0247 goto disable_resources;
0248
0249 return 0;
0250
0251 disable_resources:
0252 ahci_platform_disable_resources(hpriv);
0253 return rc;
0254 }
0255
0256 #ifdef CONFIG_PM_SLEEP
0257 static int ahci_sunxi_resume(struct device *dev)
0258 {
0259 struct ata_host *host = dev_get_drvdata(dev);
0260 struct ahci_host_priv *hpriv = host->private_data;
0261 int rc;
0262
0263 rc = ahci_platform_enable_resources(hpriv);
0264 if (rc)
0265 return rc;
0266
0267 rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
0268 if (rc)
0269 goto disable_resources;
0270
0271 rc = ahci_platform_resume_host(dev);
0272 if (rc)
0273 goto disable_resources;
0274
0275 return 0;
0276
0277 disable_resources:
0278 ahci_platform_disable_resources(hpriv);
0279 return rc;
0280 }
0281 #endif
0282
0283 static SIMPLE_DEV_PM_OPS(ahci_sunxi_pm_ops, ahci_platform_suspend,
0284 ahci_sunxi_resume);
0285
0286 static const struct of_device_id ahci_sunxi_of_match[] = {
0287 { .compatible = "allwinner,sun4i-a10-ahci", },
0288 { .compatible = "allwinner,sun8i-r40-ahci", },
0289 { }
0290 };
0291 MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match);
0292
0293 static struct platform_driver ahci_sunxi_driver = {
0294 .probe = ahci_sunxi_probe,
0295 .remove = ata_platform_remove_one,
0296 .driver = {
0297 .name = DRV_NAME,
0298 .of_match_table = ahci_sunxi_of_match,
0299 .pm = &ahci_sunxi_pm_ops,
0300 },
0301 };
0302 module_platform_driver(ahci_sunxi_driver);
0303
0304 MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA driver");
0305 MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>");
0306 MODULE_LICENSE("GPL");