aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorMark Langsdorf <mark.langsdorf@calxeda.com>2013-08-14 14:23:31 -0400
committerTejun Heo <tj@kernel.org>2013-08-14 16:43:29 -0400
commitb2e4c7b94e2826bea435aa3107e7c44f3e68515b (patch)
treeef70b3f39bf43017c4e7625ab2d212060ab95956 /drivers/ata
parent91c2095021acc6264288d58fc9f0b5b78984ac85 (diff)
sata, highbank: set tx_atten override bits
Some board designs do not drive the SATA transmit lines within the specification. The ECME can provide override settings, on a per board basis, to bring the transmit lines within spec. Read those settings from the DTB and program them in. At the time of submission, no production hardware requires this patch. Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/sata_highbank.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 5eb93de75e43..ba43c7217545 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -46,14 +46,19 @@
46#define CR_BUSY 0x0001 46#define CR_BUSY 0x0001
47#define CR_START 0x0001 47#define CR_START 0x0001
48#define CR_WR_RDN 0x0002 48#define CR_WR_RDN 0x0002
49#define CPHY_TX_INPUT_STS 0x2001
49#define CPHY_RX_INPUT_STS 0x2002 50#define CPHY_RX_INPUT_STS 0x2002
50#define CPHY_SATA_OVERRIDE 0x4000 51#define CPHY_SATA_TX_OVERRIDE 0x8000
51#define CPHY_OVERRIDE 0x2005 52#define CPHY_SATA_RX_OVERRIDE 0x4000
53#define CPHY_TX_OVERRIDE 0x2004
54#define CPHY_RX_OVERRIDE 0x2005
52#define SPHY_LANE 0x100 55#define SPHY_LANE 0x100
53#define SPHY_HALF_RATE 0x0001 56#define SPHY_HALF_RATE 0x0001
54#define CPHY_SATA_DPLL_MODE 0x0700 57#define CPHY_SATA_DPLL_MODE 0x0700
55#define CPHY_SATA_DPLL_SHIFT 8 58#define CPHY_SATA_DPLL_SHIFT 8
56#define CPHY_SATA_DPLL_RESET (1 << 11) 59#define CPHY_SATA_DPLL_RESET (1 << 11)
60#define CPHY_SATA_TX_ATTEN 0x1c00
61#define CPHY_SATA_TX_ATTEN_SHIFT 10
57#define CPHY_PHY_COUNT 6 62#define CPHY_PHY_COUNT 6
58#define CPHY_LANE_COUNT 4 63#define CPHY_LANE_COUNT 4
59#define CPHY_PORT_COUNT (CPHY_PHY_COUNT * CPHY_LANE_COUNT) 64#define CPHY_PORT_COUNT (CPHY_PHY_COUNT * CPHY_LANE_COUNT)
@@ -66,6 +71,7 @@ struct phy_lane_info {
66 void __iomem *phy_base; 71 void __iomem *phy_base;
67 u8 lane_mapping; 72 u8 lane_mapping;
68 u8 phy_devs; 73 u8 phy_devs;
74 u8 tx_atten;
69}; 75};
70static struct phy_lane_info port_data[CPHY_PORT_COUNT]; 76static struct phy_lane_info port_data[CPHY_PORT_COUNT];
71 77
@@ -76,7 +82,6 @@ static DEFINE_SPINLOCK(sgpio_lock);
76#define SGPIO_PINS 3 82#define SGPIO_PINS 3
77#define SGPIO_PORTS 8 83#define SGPIO_PORTS 8
78 84
79/* can be cast as an ahci_host_priv for compatibility with most functions */
80struct ecx_plat_data { 85struct ecx_plat_data {
81 u32 n_ports; 86 u32 n_ports;
82 unsigned sgpio_gpio[SGPIO_PINS]; 87 unsigned sgpio_gpio[SGPIO_PINS];
@@ -259,8 +264,27 @@ static void highbank_cphy_disable_overrides(u8 sata_port)
259 if (unlikely(port_data[sata_port].phy_base == NULL)) 264 if (unlikely(port_data[sata_port].phy_base == NULL))
260 return; 265 return;
261 tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); 266 tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE);
262 tmp &= ~CPHY_SATA_OVERRIDE; 267 tmp &= ~CPHY_SATA_RX_OVERRIDE;
263 combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 268 combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
269}
270
271static void cphy_override_tx_attenuation(u8 sata_port, u32 val)
272{
273 u8 lane = port_data[sata_port].lane_mapping;
274 u32 tmp;
275
276 if (val & 0x8)
277 return;
278
279 tmp = combo_phy_read(sata_port, CPHY_TX_INPUT_STS + lane * SPHY_LANE);
280 tmp &= ~CPHY_SATA_TX_OVERRIDE;
281 combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp);
282
283 tmp |= CPHY_SATA_TX_OVERRIDE;
284 combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp);
285
286 tmp |= (val << CPHY_SATA_TX_ATTEN_SHIFT) & CPHY_SATA_TX_ATTEN;
287 combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp);
264} 288}
265 289
266static void cphy_override_rx_mode(u8 sata_port, u32 val) 290static void cphy_override_rx_mode(u8 sata_port, u32 val)
@@ -268,21 +292,21 @@ static void cphy_override_rx_mode(u8 sata_port, u32 val)
268 u8 lane = port_data[sata_port].lane_mapping; 292 u8 lane = port_data[sata_port].lane_mapping;
269 u32 tmp; 293 u32 tmp;
270 tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); 294 tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE);
271 tmp &= ~CPHY_SATA_OVERRIDE; 295 tmp &= ~CPHY_SATA_RX_OVERRIDE;
272 combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 296 combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
273 297
274 tmp |= CPHY_SATA_OVERRIDE; 298 tmp |= CPHY_SATA_RX_OVERRIDE;
275 combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 299 combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
276 300
277 tmp &= ~CPHY_SATA_DPLL_MODE; 301 tmp &= ~CPHY_SATA_DPLL_MODE;
278 tmp |= val << CPHY_SATA_DPLL_SHIFT; 302 tmp |= val << CPHY_SATA_DPLL_SHIFT;
279 combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 303 combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
280 304
281 tmp |= CPHY_SATA_DPLL_RESET; 305 tmp |= CPHY_SATA_DPLL_RESET;
282 combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 306 combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
283 307
284 tmp &= ~CPHY_SATA_DPLL_RESET; 308 tmp &= ~CPHY_SATA_DPLL_RESET;
285 combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp); 309 combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp);
286 310
287 msleep(15); 311 msleep(15);
288} 312}
@@ -299,16 +323,20 @@ static void highbank_cphy_override_lane(u8 sata_port)
299 lane * SPHY_LANE); 323 lane * SPHY_LANE);
300 } while ((tmp & SPHY_HALF_RATE) && (k++ < 1000)); 324 } while ((tmp & SPHY_HALF_RATE) && (k++ < 1000));
301 cphy_override_rx_mode(sata_port, 3); 325 cphy_override_rx_mode(sata_port, 3);
326 cphy_override_tx_attenuation(sata_port, port_data[sata_port].tx_atten);
302} 327}
303 328
304static int highbank_initialize_phys(struct device *dev, void __iomem *addr) 329static int highbank_initialize_phys(struct device *dev, void __iomem *addr)
305{ 330{
306 struct device_node *sata_node = dev->of_node; 331 struct device_node *sata_node = dev->of_node;
307 int phy_count = 0, phy, port = 0; 332 int phy_count = 0, phy, port = 0, i;
308 void __iomem *cphy_base[CPHY_PHY_COUNT]; 333 void __iomem *cphy_base[CPHY_PHY_COUNT];
309 struct device_node *phy_nodes[CPHY_PHY_COUNT]; 334 struct device_node *phy_nodes[CPHY_PHY_COUNT];
335 u32 tx_atten[CPHY_PORT_COUNT];
336
310 memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT); 337 memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT);
311 memset(phy_nodes, 0, sizeof(struct device_node*) * CPHY_PHY_COUNT); 338 memset(phy_nodes, 0, sizeof(struct device_node*) * CPHY_PHY_COUNT);
339 memset(tx_atten, 0xff, CPHY_PORT_COUNT);
312 340
313 do { 341 do {
314 u32 tmp; 342 u32 tmp;
@@ -336,6 +364,10 @@ static int highbank_initialize_phys(struct device *dev, void __iomem *addr)
336 of_node_put(phy_data.np); 364 of_node_put(phy_data.np);
337 port += 1; 365 port += 1;
338 } while (port < CPHY_PORT_COUNT); 366 } while (port < CPHY_PORT_COUNT);
367 of_property_read_u32_array(sata_node, "calxeda,tx-atten",
368 tx_atten, port);
369 for (i = 0; i < port; i++)
370 port_data[i].tx_atten = (u8) tx_atten[i];
339 return 0; 371 return 0;
340} 372}
341 373