aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux-6.6/linux-yocto-6.6/0028-spi-spidev-Add-dummy-spidev-device-to-SPI-bus-for_0030-amd-xgbe-ptp-add-hw-time-stamp-changes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux-6.6/linux-yocto-6.6/0028-spi-spidev-Add-dummy-spidev-device-to-SPI-bus-for_0030-amd-xgbe-ptp-add-hw-time-stamp-changes.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux-6.6/linux-yocto-6.6/0028-spi-spidev-Add-dummy-spidev-device-to-SPI-bus-for_0030-amd-xgbe-ptp-add-hw-time-stamp-changes.patch611
1 files changed, 611 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux-6.6/linux-yocto-6.6/0028-spi-spidev-Add-dummy-spidev-device-to-SPI-bus-for_0030-amd-xgbe-ptp-add-hw-time-stamp-changes.patch b/meta-amd-bsp/recipes-kernel/linux-6.6/linux-yocto-6.6/0028-spi-spidev-Add-dummy-spidev-device-to-SPI-bus-for_0030-amd-xgbe-ptp-add-hw-time-stamp-changes.patch
new file mode 100644
index 00000000..6bf6e84f
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux-6.6/linux-yocto-6.6/0028-spi-spidev-Add-dummy-spidev-device-to-SPI-bus-for_0030-amd-xgbe-ptp-add-hw-time-stamp-changes.patch
@@ -0,0 +1,611 @@
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+index 1d936cdc13cf..57feec00e21a 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+@@ -332,6 +332,10 @@
+ #define MAC_TSSR 0x0d20
+ #define MAC_TXSNR 0x0d30
+ #define MAC_TXSSR 0x0d34
++#define MAC_TICNR 0x0d58
++#define MAC_TICSNR 0x0d5C
++#define MAC_TECNR 0x0d60
++#define MAC_TECSNR 0x0d64
+ #define MAC_AUXCR 0x0d40
+ #define MAC_ATSNR 0x0d48
+ #define MAC_ATSSR 0x0d4C
+@@ -537,6 +541,8 @@
+ #define MAC_TSCR_SNAPTYPSEL_WIDTH 2
+ #define MAC_TSCR_TSADDREG_INDEX 5
+ #define MAC_TSCR_TSADDREG_WIDTH 1
++#define MAC_TSCR_TSUPDT_INDEX 3
++#define MAC_TSCR_TSUPDT_WIDTH 1
+ #define MAC_TSCR_TSCFUPDT_INDEX 1
+ #define MAC_TSCR_TSCFUPDT_WIDTH 1
+ #define MAC_TSCR_TSCTRLSSR_INDEX 9
+@@ -578,6 +584,10 @@
+ #define MAC_TSSR_AUXTSTRIG_WIDTH 1
+ #define MAC_TXSNR_TXTSSTSMIS_INDEX 31
+ #define MAC_TXSNR_TXTSSTSMIS_WIDTH 1
++#define MAC_TICSNR_TSICSNS_INDEX 8
++#define MAC_TICSNR_TSICSNS_WIDTH 8
++#define MAC_TECSNR_TSECSNS_INDEX 8
++#define MAC_TECSNR_TSECSNS_WIDTH 8
+ #define MAC_AUXCR_ATSEN3_INDEX 7
+ #define MAC_AUXCR_ATSEN3_WIDTH 1
+ #define MAC_AUXCR_ATSEN2_INDEX 6
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+index b7061e24e643..bc1cd7d37d93 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+@@ -1635,6 +1635,28 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel)
+ DBGPR("<--rx_desc_init\n");
+ }
+
++static void xgbe_update_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec,
++ unsigned int nsec)
++{
++ unsigned int count = 10000;
++
++ /* Set the time values and tell the device */
++ XGMAC_IOWRITE(pdata, MAC_STSUR, sec);
++ XGMAC_IOWRITE(pdata, MAC_STNUR, nsec);
++
++ /* issue command to update the system time value */
++ XGMAC_IOWRITE(pdata, MAC_TSCR,
++ XGMAC_IOREAD(pdata, MAC_TSCR) | (1 << MAC_TSCR_TSUPDT_INDEX));
++
++ /* Wait for the time till update complete */
++ while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSUPDT))
++ udelay(5);
++
++ if (!count)
++ netdev_err(pdata->netdev, "timed out updating system timestamp\n");
++}
++
++
+ static void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata,
+ unsigned int addend)
+ {
+@@ -1713,8 +1735,8 @@ static void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
+ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSA) &&
+ !XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSD)) {
+ nsec = le32_to_cpu(rdesc->desc1);
+- nsec <<= 32;
+- nsec |= le32_to_cpu(rdesc->desc0);
++ nsec *= NSEC_PER_SEC;
++ nsec += le32_to_cpu(rdesc->desc0);
+ if (nsec != 0xffffffffffffffffULL) {
+ packet->rx_tstamp = nsec;
+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+@@ -1722,36 +1744,13 @@ static void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
+ }
+ }
+ }
+-
+-static int xgbe_config_tstamp(struct xgbe_prv_data *pdata,
++static void xgbe_config_tstamp(struct xgbe_prv_data *pdata,
+ unsigned int mac_tscr)
+ {
+- /* Set one nano-second accuracy */
+- XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1);
+-
+- /* Set fine timestamp update */
+- XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1);
+-
+- /* Overwrite earlier timestamps */
+- XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1);
+-
+- XGMAC_IOWRITE(pdata, MAC_TSCR, mac_tscr);
+-
+- /* Exit if timestamping is not enabled */
+- if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA))
+- return 0;
+-
+- /* Initialize time registers */
+- XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC);
+- XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC);
+- xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend);
+- xgbe_set_tstamp_time(pdata, 0, 0);
+-
+- /* Initialize the timecounter */
+- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
+- ktime_to_ns(ktime_get_real()));
+-
+- return 0;
++ unsigned int value = 0;
++ value = XGMAC_IOREAD(pdata, MAC_TSCR);
++ value |= mac_tscr;
++ XGMAC_IOWRITE(pdata, MAC_TSCR, value);
+ }
+
+ static void xgbe_tx_start_xmit(struct xgbe_channel *channel,
+@@ -1779,6 +1778,82 @@ static void xgbe_tx_start_xmit(struct xgbe_channel *channel,
+ ring->tx.xmit_more = 0;
+ }
+
++
++static void xgbe_init_ptp(struct xgbe_prv_data *pdata)
++{
++ unsigned int mac_tscr = 0;
++ struct timespec64 now;
++ u64 dividend;
++
++ /* Register Settings to be done based on the link speed. */
++ switch(pdata->phy.speed) {
++ case SPEED_1000:
++ XGMAC_IOWRITE(pdata, MAC_TICNR, MAC_TICNR_1G_INITVAL);
++ XGMAC_IOWRITE(pdata, MAC_TECNR, MAC_TECNR_1G_INITVAL);
++ break;
++ case SPEED_2500:
++ case SPEED_10000:
++ XGMAC_IOWRITE_BITS(pdata, MAC_TICSNR, TSICSNS, MAC_TICSNR_10G_INITVAL);
++ XGMAC_IOWRITE(pdata, MAC_TECNR, MAC_TECNR_10G_INITVAL);
++ XGMAC_IOWRITE_BITS(pdata, MAC_TECSNR, TSECSNS, MAC_TECSNR_10G_INITVAL);
++ break;
++ case SPEED_UNKNOWN:
++ default:
++ break;
++ }
++
++ /* Enable IEEE1588 PTP clock. */
++ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
++
++ /* Overwrite earlier timestamps */
++ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1);
++
++ /* Set one nano-second accuracy */
++ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1);
++
++ /* Set fine timestamp update */
++ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1);
++
++ xgbe_config_tstamp(pdata, mac_tscr);
++
++ /* Exit if timestamping is not enabled */
++ if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA))
++ return;
++
++ if (pdata->vdata->tstamp_ptp_clock_freq) {
++ /* Initialize time registers based on 125MHz PTP Clock Frequency */
++ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_V2_TSTAMP_SSINC);
++ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_V2_TSTAMP_SNSINC);
++ } else {
++ /* Initialize time registers based on 50MHz PTP Clock Frequency*/
++ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC);
++ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC);
++ }
++
++ /* Calculate the addend:
++ * addend = 2^32 / (PTP ref clock / (PTP clock based on SSINC))
++ * = (2^32 * (PTP clock based on SSINC)) / PTP ref clock
++ */
++ if (pdata->vdata->tstamp_ptp_clock_freq)
++ dividend = 100000000; // PTP clock frequency is 125MHz
++ else
++ dividend = 50000000; // PTP clock frequency is 50MHz
++
++ dividend <<= 32;
++ pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate);
++
++ xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend);
++
++ dma_wmb();
++ /* initialize system time */
++ ktime_get_real_ts64(&now);
++
++ /* lower 32 bits of tv_sec are safe until y2106 */
++ xgbe_set_tstamp_time(pdata, (u32)now.tv_sec, now.tv_nsec);
++
++}
++
++
+ static void xgbe_dev_xmit(struct xgbe_channel *channel)
+ {
+ struct xgbe_prv_data *pdata = channel->pdata;
+@@ -3735,9 +3810,11 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
+ hw_if->read_mmc_stats = xgbe_read_mmc_stats;
+
+ /* For PTP config */
++ hw_if->init_ptp = xgbe_init_ptp;
+ hw_if->config_tstamp = xgbe_config_tstamp;
+ hw_if->update_tstamp_addend = xgbe_update_tstamp_addend;
+ hw_if->set_tstamp_time = xgbe_set_tstamp_time;
++ hw_if->update_tstamp_time = xgbe_update_tstamp_time;
+ hw_if->get_tstamp_time = xgbe_get_tstamp_time;
+ hw_if->get_tx_tstamp = xgbe_get_tx_tstamp;
+
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+index 6923d17a2432..47502ab698cc 100755
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+@@ -1487,7 +1487,6 @@ static void xgbe_tx_tstamp(struct work_struct *work)
+ struct xgbe_prv_data,
+ tx_tstamp_work);
+ struct skb_shared_hwtstamps hwtstamps;
+- u64 nsec;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdata->tstamp_lock, flags);
+@@ -1495,11 +1494,9 @@ static void xgbe_tx_tstamp(struct work_struct *work)
+ goto unlock;
+
+ if (pdata->tx_tstamp) {
+- nsec = timecounter_cyc2time(&pdata->tstamp_tc,
+- pdata->tx_tstamp);
+
+ memset(&hwtstamps, 0, sizeof(hwtstamps));
+- hwtstamps.hwtstamp = ns_to_ktime(nsec);
++ hwtstamps.hwtstamp = ns_to_ktime(pdata->tx_tstamp);
+ skb_tstamp_tx(pdata->tx_tstamp_skb, &hwtstamps);
+ }
+
+@@ -1885,7 +1882,8 @@ static int xgbe_open(struct net_device *netdev)
+ INIT_WORK(&pdata->restart_work, xgbe_restart);
+ INIT_WORK(&pdata->stopdev_work, xgbe_stopdev);
+ INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp);
+-
++/* Initialize PTP timestamping and clock. */
++ pdata->hw_if.init_ptp(pdata);
+ ret = xgbe_alloc_memory(pdata);
+ if (ret)
+ goto err_ptpclk;
+@@ -2649,12 +2647,9 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
+
+ if (XGMAC_GET_BITS(packet->attributes,
+ RX_PACKET_ATTRIBUTES, RX_TSTAMP)) {
+- u64 nsec;
+
+- nsec = timecounter_cyc2time(&pdata->tstamp_tc,
+- packet->rx_tstamp);
+ hwtstamps = skb_hwtstamps(skb);
+- hwtstamps->hwtstamp = ns_to_ktime(nsec);
++ hwtstamps->hwtstamp = ns_to_ktime(packet->rx_tstamp);
+ }
+
+ if (XGMAC_GET_BITS(packet->attributes,
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+index 397b350902a2..b0eaa933f00b 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+@@ -482,6 +482,7 @@ static struct xgbe_version_data xgbe_v2a = {
+ .tx_max_fifo_size = 229376,
+ .rx_max_fifo_size = 229376,
+ .tx_tstamp_workaround = 1,
++ .tstamp_ptp_clock_freq = 1,
+ .ecc_support = 1,
+ .i2c_support = 1,
+ .irq_reissue_support = 1,
+@@ -498,6 +499,7 @@ static struct xgbe_version_data xgbe_v2b = {
+ .tx_max_fifo_size = 65536,
+ .rx_max_fifo_size = 65536,
+ .tx_tstamp_workaround = 1,
++ .tstamp_ptp_clock_freq = 1,
+ .ecc_support = 1,
+ .i2c_support = 1,
+ .irq_reissue_support = 1,
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
+index 648a85070219..a953bbfcfadb 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
+@@ -122,17 +122,6 @@
+ #include "xgbe.h"
+ #include "xgbe-common.h"
+
+-static u64 xgbe_cc_read(const struct cyclecounter *cc)
+-{
+- struct xgbe_prv_data *pdata = container_of(cc,
+- struct xgbe_prv_data,
+- tstamp_cc);
+- u64 nsec;
+-
+- nsec = pdata->hw_if.get_tstamp_time(pdata);
+-
+- return nsec;
+-}
+
+ static int xgbe_adjfine(struct ptp_clock_info *info, long scaled_ppm)
+ {
+@@ -140,6 +129,29 @@ static int xgbe_adjfine(struct ptp_clock_info *info, long scaled_ppm)
+ struct xgbe_prv_data,
+ ptp_clock_info);
+ unsigned long flags;
++ unsigned int sec, nsec;
++ unsigned int neg_adjust = 0;
++ u32 quotient, reminder;
++
++ if (delta < 0) {
++ neg_adjust = 1;
++ delta = -delta;
++ }
++
++ quotient = div_u64_rem(delta, 1000000000ULL, &reminder);
++ sec = quotient;
++ nsec = reminder;
++
++ /* Negative adjustment for Hw timer register. */
++ if (neg_adjust) {
++ sec = -sec;
++ if (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSCTRLSSR))
++ nsec = (1000000000UL - nsec);
++ else
++ nsec = (0x80000000UL - nsec);
++ }
++ nsec = (neg_adjust << 31) | nsec;
++
+ u64 addend;
+
+ addend = adjust_by_scaled_ppm(pdata->tstamp_addend, scaled_ppm);
+@@ -167,17 +179,25 @@ static int xgbe_adjtime(struct ptp_clock_info *info, s64 delta)
+ return 0;
+ }
+
+-static int xgbe_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
++static int xgbe_gettimex(struct ptp_clock_info *info,
++ struct timespec64 *ts,
++ struct ptp_system_timestamp *sts)
+ {
+ struct xgbe_prv_data *pdata = container_of(info,
+ struct xgbe_prv_data,
+ ptp_clock_info);
+ unsigned long flags;
+ u64 nsec;
++ static int count = 3;
+
++ if (count > 0 && count--)
++ dump_stack();
+ spin_lock_irqsave(&pdata->tstamp_lock, flags);
+
+- nsec = timecounter_read(&pdata->tstamp_tc);
++ ptp_read_system_prets(sts);
++ nsec = pdata->hw_if.get_tstamp_time(pdata);
++ ptp_read_system_postts(sts);
++
+
+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+
+@@ -193,13 +213,10 @@ static int xgbe_settime(struct ptp_clock_info *info,
+ struct xgbe_prv_data,
+ ptp_clock_info);
+ unsigned long flags;
+- u64 nsec;
+
+- nsec = timespec64_to_ns(ts);
+
+ spin_lock_irqsave(&pdata->tstamp_lock, flags);
+-
+- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec);
++ pdata->hw_if.set_tstamp_time(pdata, ts->tv_sec, ts->tv_nsec);
+
+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+
+@@ -268,22 +285,6 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
+
+ pdata->ptp_clock = clock;
+
+- /* Calculate the addend:
+- * addend = 2^32 / (PTP ref clock / 50Mhz)
+- * = (2^32 * 50Mhz) / PTP ref clock
+- */
+- dividend = 50000000;
+- dividend <<= 32;
+- pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate);
+-
+- /* Setup the timecounter */
+- cc->read = xgbe_cc_read;
+- cc->mask = CLOCKSOURCE_MASK(64);
+- cc->mult = 1;
+- cc->shift = 0;
+-
+- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
+- ktime_to_ns(ktime_get_real()));
+
+ /* Disable all timestamping to start */
+ XGMAC_IOWRITE(pdata, MAC_TSCR, 0);
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
+index 11df8e463c2f..7eff27409e6d 100755
+--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
+@@ -225,6 +225,14 @@
+ /* PCI MSI/MSIx support */
+ #define XGBE_MSI_BASE_COUNT 4
+ #define XGBE_MSI_MIN_COUNT (XGBE_MSI_BASE_COUNT + 1)
++/* Initial PTP register values based on Link Speed. */
++#define MAC_TICNR_1G_INITVAL 0x10
++#define MAC_TECNR_1G_INITVAL 0x28
++
++#define MAC_TICSNR_10G_INITVAL 0x33
++#define MAC_TECNR_10G_INITVAL 0x14
++#define MAC_TECSNR_10G_INITVAL 0xCC
++
+
+ /* PCI clock frequencies */
+ #define XGBE_V2_DMA_CLOCK_FREQ 500000000 /* 500 MHz */
+@@ -235,6 +243,9 @@
+ */
+ #define XGBE_TSTAMP_SSINC 20
+ #define XGBE_TSTAMP_SNSINC 0
++#define XGBE_V2_TSTAMP_SSINC 0xA
++#define XGBE_V2_TSTAMP_SNSINC 0
++
+
+ /* Driver PMT macros */
+ #define XGMAC_DRIVER_CONTEXT 1
+@@ -846,10 +857,15 @@ struct xgbe_hw_if {
+ void (*read_mmc_stats)(struct xgbe_prv_data *);
+
+ /* For Timestamp config */
+- int (*config_tstamp)(struct xgbe_prv_data *, unsigned int);
++ void (*init_ptp)(struct xgbe_prv_data *);
++ void (*config_tstamp)(struct xgbe_prv_data *, unsigned int);
++
+ void (*update_tstamp_addend)(struct xgbe_prv_data *, unsigned int);
+ void (*set_tstamp_time)(struct xgbe_prv_data *, unsigned int sec,
+ unsigned int nsec);
++ void (*update_tstamp_time)(struct xgbe_prv_data *, unsigned int sec,
++ unsigned int nsec);
++
+ u64 (*get_tstamp_time)(struct xgbe_prv_data *);
+ u64 (*get_tx_tstamp)(struct xgbe_prv_data *);
+ u64 (*get_aux_snp)(struct xgbe_prv_data *);
+@@ -1050,6 +1066,7 @@ struct xgbe_version_data {
+ unsigned int tx_max_fifo_size;
+ unsigned int rx_max_fifo_size;
+ unsigned int tx_tstamp_workaround;
++ unsigned int tstamp_ptp_clock_freq;
+ unsigned int ecc_support;
+ unsigned int i2c_support;
+ unsigned int irq_reissue_support;
+@@ -1236,8 +1253,6 @@ struct xgbe_prv_data {
+ struct ptp_clock_info ptp_clock_info;
+ struct ptp_clock *ptp_clock;
+ struct hwtstamp_config tstamp_config;
+- struct cyclecounter tstamp_cc;
+- struct timecounter tstamp_tc;
+ unsigned int tstamp_addend;
+ struct work_struct tx_tstamp_work;
+ struct sk_buff *tx_tstamp_skb;
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index 399e81d37b3b..ed189bb3de8e 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -3373,6 +3373,43 @@ int spi_controller_resume(struct spi_controller *ctlr)
+ }
+ EXPORT_SYMBOL_GPL(spi_controller_resume);
+
++static int __spi_controller_match(struct device *dev, const void *data)
++{
++ struct spi_controller *ctlr;
++ const u16 *bus_num = data;
++
++ ctlr = container_of(dev, struct spi_controller, dev);
++ return ctlr->bus_num == *bus_num;
++}
++
++/**
++ * spi_busnum_to_master - look up master associated with bus_num
++ * @bus_num: the master's bus number
++ * Context: can sleep
++ *
++ * This call may be used with devices that are registered after
++ * arch init time. It returns a refcounted pointer to the relevant
++ * spi_controller (which the caller must release), or NULL if there is
++ * no such master registered.
++ *
++ * Return: the SPI master structure on success, else NULL.
++ */
++struct spi_controller *spi_busnum_to_master(u16 bus_num)
++{
++ struct device *dev;
++ struct spi_controller *ctlr = NULL;
++
++ dev = class_find_device(&spi_master_class, NULL, &bus_num,
++ __spi_controller_match);
++ if (dev)
++ ctlr = container_of(dev, struct spi_controller, dev);
++ /* reference got in class_find_device */
++ return ctlr;
++}
++EXPORT_SYMBOL_GPL(spi_busnum_to_master);
++
++
++
+ /*-------------------------------------------------------------------------*/
+
+ /* Core methods for spi_message alterations */
+diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
+index d13dc15cc191..ce39aa46fa3f 100644
+--- a/drivers/spi/spidev.c
++++ b/drivers/spi/spidev.c
+@@ -26,7 +26,9 @@
+
+ #include <linux/uaccess.h>
+
+-
++#define SPI_BUS 0
++#define SPI_BUS_CS1 0
++
+ /*
+ * This supports access to SPI devices using normal userspace I/O calls.
+ * Note that while traditional UNIX/POSIX I/O semantics are half duplex,
+@@ -712,6 +714,7 @@ static const struct spi_device_id spidev_spi_ids[] = {
+ { .name = "m53cpld" },
+ { .name = "spi-petra" },
+ { .name = "spi-authenta" },
++ { .name = "spidev" },
+ { .name = "em3581" },
+ { .name = "si3210" },
+ {},
+@@ -768,7 +771,7 @@ static const struct acpi_device_id spidev_acpi_ids[] = {
+ MODULE_DEVICE_TABLE(acpi, spidev_acpi_ids);
+
+ /*-------------------------------------------------------------------------*/
+-
++struct spi_device *spi_device;
+ static int spidev_probe(struct spi_device *spi)
+ {
+ int (*match)(struct device *dev);
+@@ -828,6 +831,30 @@ static int spidev_probe(struct spi_device *spi)
+ return status;
+ }
+
++static int __init add_spi_device_to_bus(void)
++{
++ struct spi_master *spi_master;
++ struct spi_board_info spi_info;
++
++ spi_master = spi_busnum_to_master(SPI_BUS);
++ if (!spi_master) {
++ printk(KERN_ALERT "Please make sure to \'modprobe "
++ "spi_amd\' driver first\n");
++ return -1;
++ }
++ memset(&spi_info, 0, sizeof(struct spi_board_info));
++
++ strlcpy(spi_info.modalias, "spidev", SPI_NAME_SIZE);
++ spi_info.bus_num = SPI_BUS; //Bus number of SPI master
++ spi_info.chip_select = SPI_BUS_CS1; //CS on which SPI device is connected
++
++ spi_device = spi_new_device(spi_master, &spi_info);
++ if (!spi_device)
++ return -ENODEV;
++
++ return 0;
++}
++
+ static void spidev_remove(struct spi_device *spi)
+ {
+ struct spidev_data *spidev = spi_get_drvdata(spi);
+@@ -889,6 +916,12 @@ static int __init spidev_init(void)
+ class_destroy(spidev_class);
+ unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
+ }
++ status = add_spi_device_to_bus();
++ if (status < 0) {
++ spi_unregister_driver(&spidev_spi_driver);
++ class_destroy(spidev_class);
++ unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
++ }
+ return status;
+ }
+ module_init(spidev_init);
+@@ -896,6 +929,7 @@ module_init(spidev_init);
+ static void __exit spidev_exit(void)
+ {
+ spi_unregister_driver(&spidev_spi_driver);
++ spi_unregister_device(spi_device);
+ class_destroy(spidev_class);
+ unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
+ }
+diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
+index 8cc7a99927f9..7b5d87f1ddaf 100644
+--- a/include/linux/spi/spi.h
++++ b/include/linux/spi/spi.h
+@@ -873,7 +873,7 @@ extern struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,
+ int index);
+ int acpi_spi_count_resources(struct acpi_device *adev);
+ #endif
+-
++extern struct spi_controller *spi_busnum_to_master(u16 busnum);
+ /*
+ * SPI resource management while processing a SPI message
+ */