]> Pileus Git - ~andy/linux/blobdiff - drivers/ata/sata_highbank.c
Merge branch 'for-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata
[~andy/linux] / drivers / ata / sata_highbank.c
index e9a4f46d962e817ab21aa44e155d399f07e76132..7f5e5d96327fcbb3a08994ae01f910f824a0c623 100644 (file)
 #define CR_BUSY                                0x0001
 #define CR_START                       0x0001
 #define CR_WR_RDN                      0x0002
+#define CPHY_TX_INPUT_STS              0x2001
 #define CPHY_RX_INPUT_STS              0x2002
-#define CPHY_SATA_OVERRIDE             0x4000
-#define CPHY_OVERRIDE                  0x2005
+#define CPHY_SATA_TX_OVERRIDE          0x8000
+#define CPHY_SATA_RX_OVERRIDE          0x4000
+#define CPHY_TX_OVERRIDE               0x2004
+#define CPHY_RX_OVERRIDE               0x2005
 #define SPHY_LANE                      0x100
 #define SPHY_HALF_RATE                 0x0001
 #define CPHY_SATA_DPLL_MODE            0x0700
 #define CPHY_SATA_DPLL_SHIFT           8
 #define CPHY_SATA_DPLL_RESET           (1 << 11)
+#define CPHY_SATA_TX_ATTEN             0x1c00
+#define CPHY_SATA_TX_ATTEN_SHIFT       10
 #define CPHY_PHY_COUNT                 6
 #define CPHY_LANE_COUNT                        4
 #define CPHY_PORT_COUNT                        (CPHY_PHY_COUNT * CPHY_LANE_COUNT)
@@ -66,6 +71,7 @@ struct phy_lane_info {
        void __iomem *phy_base;
        u8 lane_mapping;
        u8 phy_devs;
+       u8 tx_atten;
 };
 static struct phy_lane_info port_data[CPHY_PORT_COUNT];
 
@@ -76,9 +82,11 @@ static DEFINE_SPINLOCK(sgpio_lock);
 #define SGPIO_PINS                     3
 #define SGPIO_PORTS                    8
 
-/* can be cast as an ahci_host_priv for compatibility with most functions */
 struct ecx_plat_data {
        u32             n_ports;
+       /* number of extra clocks that the SGPIO PIC controller expects */
+       u32             pre_clocks;
+       u32             post_clocks;
        unsigned        sgpio_gpio[SGPIO_PINS];
        u32             sgpio_pattern;
        u32             port_to_sgpio[SGPIO_PORTS];
@@ -155,6 +163,9 @@ static ssize_t ecx_transmit_led_message(struct ata_port *ap, u32 state,
        spin_lock_irqsave(&sgpio_lock, flags);
        ecx_parse_sgpio(pdata, ap->port_no, state);
        sgpio_out = pdata->sgpio_pattern;
+       for (i = 0; i < pdata->pre_clocks; i++)
+               ecx_led_cycle_clock(pdata);
+
        gpio_set_value(pdata->sgpio_gpio[SLOAD], 1);
        ecx_led_cycle_clock(pdata);
        gpio_set_value(pdata->sgpio_gpio[SLOAD], 0);
@@ -167,6 +178,8 @@ static ssize_t ecx_transmit_led_message(struct ata_port *ap, u32 state,
                sgpio_out >>= 1;
                ecx_led_cycle_clock(pdata);
        }
+       for (i = 0; i < pdata->post_clocks; i++)
+               ecx_led_cycle_clock(pdata);
 
        /* save off new led state for port/slot */
        emp->led_state = state;
@@ -201,6 +214,11 @@ static void highbank_set_em_messages(struct device *dev,
        of_property_read_u32_array(np, "calxeda,led-order",
                                                pdata->port_to_sgpio,
                                                pdata->n_ports);
+       if (of_property_read_u32(np, "calxeda,pre-clocks", &pdata->pre_clocks))
+               pdata->pre_clocks = 0;
+       if (of_property_read_u32(np, "calxeda,post-clocks",
+                               &pdata->post_clocks))
+               pdata->post_clocks = 0;
 
        /* store em_loc */
        hpriv->em_loc = 0;
@@ -259,8 +277,27 @@ static void highbank_cphy_disable_overrides(u8 sata_port)
        if (unlikely(port_data[sata_port].phy_base == NULL))
                return;
        tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE);
-       tmp &= ~CPHY_SATA_OVERRIDE;
-       combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+       tmp &= ~CPHY_SATA_RX_OVERRIDE;
+       combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
+}
+
+static void cphy_override_tx_attenuation(u8 sata_port, u32 val)
+{
+       u8 lane = port_data[sata_port].lane_mapping;
+       u32 tmp;
+
+       if (val & 0x8)
+               return;
+
+       tmp = combo_phy_read(sata_port, CPHY_TX_INPUT_STS + lane * SPHY_LANE);
+       tmp &= ~CPHY_SATA_TX_OVERRIDE;
+       combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp);
+
+       tmp |= CPHY_SATA_TX_OVERRIDE;
+       combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp);
+
+       tmp |= (val << CPHY_SATA_TX_ATTEN_SHIFT) & CPHY_SATA_TX_ATTEN;
+       combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp);
 }
 
 static void cphy_override_rx_mode(u8 sata_port, u32 val)
@@ -268,21 +305,21 @@ static void cphy_override_rx_mode(u8 sata_port, u32 val)
        u8 lane = port_data[sata_port].lane_mapping;
        u32 tmp;
        tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE);
-       tmp &= ~CPHY_SATA_OVERRIDE;
-       combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+       tmp &= ~CPHY_SATA_RX_OVERRIDE;
+       combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
 
-       tmp |= CPHY_SATA_OVERRIDE;
-       combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+       tmp |= CPHY_SATA_RX_OVERRIDE;
+       combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
 
        tmp &= ~CPHY_SATA_DPLL_MODE;
        tmp |= val << CPHY_SATA_DPLL_SHIFT;
-       combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+       combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
 
        tmp |= CPHY_SATA_DPLL_RESET;
-       combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+       combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
 
        tmp &= ~CPHY_SATA_DPLL_RESET;
-       combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+       combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
 
        msleep(15);
 }
@@ -299,16 +336,20 @@ static void highbank_cphy_override_lane(u8 sata_port)
                                                lane * SPHY_LANE);
        } while ((tmp & SPHY_HALF_RATE) && (k++ < 1000));
        cphy_override_rx_mode(sata_port, 3);
+       cphy_override_tx_attenuation(sata_port, port_data[sata_port].tx_atten);
 }
 
 static int highbank_initialize_phys(struct device *dev, void __iomem *addr)
 {
        struct device_node *sata_node = dev->of_node;
-       int phy_count = 0, phy, port = 0;
+       int phy_count = 0, phy, port = 0, i;
        void __iomem *cphy_base[CPHY_PHY_COUNT];
        struct device_node *phy_nodes[CPHY_PHY_COUNT];
+       u32 tx_atten[CPHY_PORT_COUNT];
+
        memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT);
        memset(phy_nodes, 0, sizeof(struct device_node*) * CPHY_PHY_COUNT);
+       memset(tx_atten, 0xff, CPHY_PORT_COUNT);
 
        do {
                u32 tmp;
@@ -336,6 +377,10 @@ static int highbank_initialize_phys(struct device *dev, void __iomem *addr)
                of_node_put(phy_data.np);
                port += 1;
        } while (port < CPHY_PORT_COUNT);
+       of_property_read_u32_array(sata_node, "calxeda,tx-atten",
+                               tx_atten, port);
+       for (i = 0; i < port; i++)
+               port_data[i].tx_atten = (u8) tx_atten[i];
        return 0;
 }
 
@@ -479,6 +524,9 @@ static int ahci_highbank_probe(struct platform_device *pdev)
        if (hpriv->cap & HOST_CAP_PMP)
                pi.flags |= ATA_FLAG_PMP;
 
+       if (hpriv->cap & HOST_CAP_64)
+               dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
+
        /* CAP.NP sometimes indicate the index of the last enabled
         * port, at other times, that of the last possible port, so
         * determining the maximum port number requires looking at