0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/init.h>
0010 #include <linux/module.h>
0011 #include <linux/export.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/clk.h>
0014 #include <linux/of.h>
0015 #include <linux/ahci_platform.h>
0016 #include <linux/libata.h>
0017 #include <linux/reset.h>
0018 #include <linux/io.h>
0019 #include <linux/dma-mapping.h>
0020
0021 #include "ahci.h"
0022
0023 #define DRV_NAME "st_ahci"
0024
0025 #define ST_AHCI_OOBR 0xbc
0026 #define ST_AHCI_OOBR_WE BIT(31)
0027 #define ST_AHCI_OOBR_CWMIN_SHIFT 24
0028 #define ST_AHCI_OOBR_CWMAX_SHIFT 16
0029 #define ST_AHCI_OOBR_CIMIN_SHIFT 8
0030 #define ST_AHCI_OOBR_CIMAX_SHIFT 0
0031
0032 struct st_ahci_drv_data {
0033 struct platform_device *ahci;
0034 struct reset_control *pwr;
0035 struct reset_control *sw_rst;
0036 struct reset_control *pwr_rst;
0037 };
0038
0039 static void st_ahci_configure_oob(void __iomem *mmio)
0040 {
0041 unsigned long old_val, new_val;
0042
0043 new_val = (0x02 << ST_AHCI_OOBR_CWMIN_SHIFT) |
0044 (0x04 << ST_AHCI_OOBR_CWMAX_SHIFT) |
0045 (0x08 << ST_AHCI_OOBR_CIMIN_SHIFT) |
0046 (0x0C << ST_AHCI_OOBR_CIMAX_SHIFT);
0047
0048 old_val = readl(mmio + ST_AHCI_OOBR);
0049 writel(old_val | ST_AHCI_OOBR_WE, mmio + ST_AHCI_OOBR);
0050 writel(new_val | ST_AHCI_OOBR_WE, mmio + ST_AHCI_OOBR);
0051 writel(new_val, mmio + ST_AHCI_OOBR);
0052 }
0053
0054 static int st_ahci_deassert_resets(struct ahci_host_priv *hpriv,
0055 struct device *dev)
0056 {
0057 struct st_ahci_drv_data *drv_data = hpriv->plat_data;
0058 int err;
0059
0060 if (drv_data->pwr) {
0061 err = reset_control_deassert(drv_data->pwr);
0062 if (err) {
0063 dev_err(dev, "unable to bring out of pwrdwn\n");
0064 return err;
0065 }
0066 }
0067
0068 if (drv_data->sw_rst) {
0069 err = reset_control_deassert(drv_data->sw_rst);
0070 if (err) {
0071 dev_err(dev, "unable to bring out of sw-rst\n");
0072 return err;
0073 }
0074 }
0075
0076 if (drv_data->pwr_rst) {
0077 err = reset_control_deassert(drv_data->pwr_rst);
0078 if (err) {
0079 dev_err(dev, "unable to bring out of pwr-rst\n");
0080 return err;
0081 }
0082 }
0083
0084 return 0;
0085 }
0086
0087 static void st_ahci_host_stop(struct ata_host *host)
0088 {
0089 struct ahci_host_priv *hpriv = host->private_data;
0090 struct st_ahci_drv_data *drv_data = hpriv->plat_data;
0091 struct device *dev = host->dev;
0092 int err;
0093
0094 if (drv_data->pwr) {
0095 err = reset_control_assert(drv_data->pwr);
0096 if (err)
0097 dev_err(dev, "unable to pwrdwn\n");
0098 }
0099
0100 ahci_platform_disable_resources(hpriv);
0101 }
0102
0103 static int st_ahci_probe_resets(struct ahci_host_priv *hpriv,
0104 struct device *dev)
0105 {
0106 struct st_ahci_drv_data *drv_data = hpriv->plat_data;
0107
0108 drv_data->pwr = devm_reset_control_get(dev, "pwr-dwn");
0109 if (IS_ERR(drv_data->pwr)) {
0110 dev_info(dev, "power reset control not defined\n");
0111 drv_data->pwr = NULL;
0112 }
0113
0114 drv_data->sw_rst = devm_reset_control_get(dev, "sw-rst");
0115 if (IS_ERR(drv_data->sw_rst)) {
0116 dev_info(dev, "soft reset control not defined\n");
0117 drv_data->sw_rst = NULL;
0118 }
0119
0120 drv_data->pwr_rst = devm_reset_control_get(dev, "pwr-rst");
0121 if (IS_ERR(drv_data->pwr_rst)) {
0122 dev_dbg(dev, "power soft reset control not defined\n");
0123 drv_data->pwr_rst = NULL;
0124 }
0125
0126 return st_ahci_deassert_resets(hpriv, dev);
0127 }
0128
0129 static struct ata_port_operations st_ahci_port_ops = {
0130 .inherits = &ahci_platform_ops,
0131 .host_stop = st_ahci_host_stop,
0132 };
0133
0134 static const struct ata_port_info st_ahci_port_info = {
0135 .flags = AHCI_FLAG_COMMON,
0136 .pio_mask = ATA_PIO4,
0137 .udma_mask = ATA_UDMA6,
0138 .port_ops = &st_ahci_port_ops,
0139 };
0140
0141 static struct scsi_host_template ahci_platform_sht = {
0142 AHCI_SHT(DRV_NAME),
0143 };
0144
0145 static int st_ahci_probe(struct platform_device *pdev)
0146 {
0147 struct device *dev = &pdev->dev;
0148 struct st_ahci_drv_data *drv_data;
0149 struct ahci_host_priv *hpriv;
0150 int err;
0151
0152 drv_data = devm_kzalloc(&pdev->dev, sizeof(*drv_data), GFP_KERNEL);
0153 if (!drv_data)
0154 return -ENOMEM;
0155
0156 hpriv = ahci_platform_get_resources(pdev, 0);
0157 if (IS_ERR(hpriv))
0158 return PTR_ERR(hpriv);
0159 hpriv->plat_data = drv_data;
0160
0161 err = st_ahci_probe_resets(hpriv, &pdev->dev);
0162 if (err)
0163 return err;
0164
0165 err = ahci_platform_enable_resources(hpriv);
0166 if (err)
0167 return err;
0168
0169 st_ahci_configure_oob(hpriv->mmio);
0170
0171 of_property_read_u32(dev->of_node,
0172 "ports-implemented", &hpriv->force_port_map);
0173
0174 err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info,
0175 &ahci_platform_sht);
0176 if (err) {
0177 ahci_platform_disable_resources(hpriv);
0178 return err;
0179 }
0180
0181 return 0;
0182 }
0183
0184 #ifdef CONFIG_PM_SLEEP
0185 static int st_ahci_suspend(struct device *dev)
0186 {
0187 struct ata_host *host = dev_get_drvdata(dev);
0188 struct ahci_host_priv *hpriv = host->private_data;
0189 struct st_ahci_drv_data *drv_data = hpriv->plat_data;
0190 int err;
0191
0192 err = ahci_platform_suspend_host(dev);
0193 if (err)
0194 return err;
0195
0196 if (drv_data->pwr) {
0197 err = reset_control_assert(drv_data->pwr);
0198 if (err) {
0199 dev_err(dev, "unable to pwrdwn");
0200 return err;
0201 }
0202 }
0203
0204 ahci_platform_disable_resources(hpriv);
0205
0206 return 0;
0207 }
0208
0209 static int st_ahci_resume(struct device *dev)
0210 {
0211 struct ata_host *host = dev_get_drvdata(dev);
0212 struct ahci_host_priv *hpriv = host->private_data;
0213 int err;
0214
0215 err = ahci_platform_enable_resources(hpriv);
0216 if (err)
0217 return err;
0218
0219 err = st_ahci_deassert_resets(hpriv, dev);
0220 if (err) {
0221 ahci_platform_disable_resources(hpriv);
0222 return err;
0223 }
0224
0225 st_ahci_configure_oob(hpriv->mmio);
0226
0227 return ahci_platform_resume_host(dev);
0228 }
0229 #endif
0230
0231 static SIMPLE_DEV_PM_OPS(st_ahci_pm_ops, st_ahci_suspend, st_ahci_resume);
0232
0233 static const struct of_device_id st_ahci_match[] = {
0234 { .compatible = "st,ahci", },
0235 { }
0236 };
0237 MODULE_DEVICE_TABLE(of, st_ahci_match);
0238
0239 static struct platform_driver st_ahci_driver = {
0240 .driver = {
0241 .name = DRV_NAME,
0242 .pm = &st_ahci_pm_ops,
0243 .of_match_table = of_match_ptr(st_ahci_match),
0244 },
0245 .probe = st_ahci_probe,
0246 .remove = ata_platform_remove_one,
0247 };
0248 module_platform_driver(st_ahci_driver);
0249
0250 MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
0251 MODULE_AUTHOR("Francesco Virlinzi <francesco.virlinzi@st.com>");
0252 MODULE_DESCRIPTION("STMicroelectronics SATA AHCI Driver");
0253 MODULE_LICENSE("GPL v2");