1
1
/*
2
2
* dx010_cpld.c - driver for SeaStone's CPLD
3
3
*
4
- * Copyright (C) 2017 Celestica Corp.
4
+ * Copyright (C) 2023 Celestica Corp.
5
5
*
6
6
* This program is free software; you can redistribute it and/or modify
7
7
* it under the terms of the GNU General Public License as published by
120
120
#define SSRR_ID_BANK2 0x296
121
121
#define SSRR_ID_BANK3 0x396
122
122
123
- #define HST_CNTL2_QUICK 0x00
124
- #define HST_CNTL2_BYTE 0x01
125
- #define HST_CNTL2_BYTE_DATA 0x02
126
- #define HST_CNTL2_WORD_DATA 0x03
127
- #define HST_CNTL2_BLOCK 0x05
123
+ #define SSRR_MASTER_ERR 0x80
124
+ #define SSRR_BUS_BUSY 0x40
125
+
126
+ #define I2C_BAUD_RATE_100K 0x40
127
+
128
128
129
129
struct dx010_i2c_data {
130
130
int portid ;
@@ -610,6 +610,166 @@ static int i2c_read_eeprom(struct i2c_adapter *a, u16 addr,
610
610
return error ;
611
611
}
612
612
613
+
614
+ /**
615
+ * Read/Write eeprom of CPLD connected QSFP device.
616
+ * @param a i2c adapter.
617
+ * @param addr address to read.
618
+ * @param new_data QSFP port number struct.
619
+ * @param rw read/write flag
620
+ * @param cmd i2c command.
621
+ * @param size access size
622
+ * @return 0 if not error, else the error code.
623
+ */
624
+ static int dx010_cpld_i2c_access (struct i2c_adapter * a , u16 addr ,
625
+ struct dx010_i2c_data * new_data , char rw ,
626
+ u8 cmd , int size , union i2c_smbus_data * data )
627
+ {
628
+ u32 reg ;
629
+ int ioBase = 0 ;
630
+ char byte ;
631
+ char data_len = 0 ;
632
+ short temp ;
633
+ short portid , opcode , devaddr , cmdbyte0 , ssrr , writedata , readdata ;
634
+ __u16 word_data ;
635
+ __u8 byte_data ;
636
+ int error = - EIO ;
637
+
638
+ mutex_lock (& cpld_data -> cpld_lock );
639
+
640
+ if (((new_data -> portid >= PORT_BANK1_START )
641
+ && (new_data -> portid <= PORT_BANK1_END ))
642
+ || (new_data -> portid == PORT_SFPP1 )
643
+ || (new_data -> portid == PORT_SFPP2 ))
644
+ {
645
+ portid = PORT_ID_BANK1 ;
646
+ opcode = OPCODE_ID_BANK1 ;
647
+ devaddr = DEVADDR_ID_BANK1 ;
648
+ cmdbyte0 = CMDBYT_ID_BANK1 ;
649
+ ssrr = SSRR_ID_BANK1 ;
650
+ writedata = WRITE_ID_BANK1 ;
651
+ readdata = READ_ID_BANK1 ;
652
+ }else if ((new_data -> portid >= PORT_BANK2_START ) && (new_data -> portid <= PORT_BANK2_END )){
653
+ portid = PORT_ID_BANK2 ;
654
+ opcode = OPCODE_ID_BANK2 ;
655
+ devaddr = DEVADDR_ID_BANK2 ;
656
+ cmdbyte0 = CMDBYT_ID_BANK2 ;
657
+ ssrr = SSRR_ID_BANK2 ;
658
+ writedata = WRITE_ID_BANK2 ;
659
+ readdata = READ_ID_BANK2 ;
660
+ }else if ((new_data -> portid >= PORT_BANK3_START ) && (new_data -> portid <= PORT_BANK3_END )){
661
+ portid = PORT_ID_BANK3 ;
662
+ opcode = OPCODE_ID_BANK3 ;
663
+ devaddr = DEVADDR_ID_BANK3 ;
664
+ cmdbyte0 = CMDBYT_ID_BANK3 ;
665
+ ssrr = SSRR_ID_BANK3 ;
666
+ writedata = WRITE_ID_BANK3 ;
667
+ readdata = READ_ID_BANK3 ;
668
+ }else {
669
+ /* Invalid parameter! */
670
+ error = - EINVAL ;
671
+ goto exit ;
672
+ }
673
+
674
+ if (size == I2C_SMBUS_BYTE || size == I2C_SMBUS_BYTE_DATA )
675
+ data_len = 1 ;
676
+ else if (size == I2C_SMBUS_WORD_DATA )
677
+ data_len = 2 ;
678
+ else {
679
+ error = - EINVAL ;
680
+ goto exit ;
681
+ }
682
+
683
+ while ((inb (ioBase + ssrr ) & SSRR_BUS_BUSY ));
684
+ if ((inb (ioBase + ssrr ) & SSRR_MASTER_ERR ) == SSRR_MASTER_ERR ) {
685
+ error = - EIO ;
686
+ /* Read error reset the port */
687
+ outb (0x00 , ioBase + ssrr );
688
+ udelay (3000 );
689
+ outb (0x01 , ioBase + ssrr );
690
+ goto exit ;
691
+ }
692
+
693
+ byte = I2C_BAUD_RATE_100K + new_data -> portid ;
694
+ reg = cmd ;
695
+ outb (byte , ioBase + portid );
696
+ outb (reg , ioBase + cmdbyte0 );
697
+ byte = (data_len << 4 ) | 0x1 ;
698
+ outb (byte , ioBase + opcode );
699
+ addr = addr << 1 ;
700
+ if (rw == I2C_SMBUS_READ )
701
+ {
702
+ addr |= 0x01 ;
703
+ outb (addr , ioBase + devaddr );
704
+ while ((inb (ioBase + ssrr ) & SSRR_BUS_BUSY ))
705
+ {
706
+ udelay (100 );
707
+ }
708
+
709
+ if ((inb (ioBase + ssrr ) & SSRR_MASTER_ERR ) == SSRR_MASTER_ERR ) {
710
+ /* Read error reset the port */
711
+ error = - EIO ;
712
+ outb (0x00 , ioBase + ssrr );
713
+ udelay (3000 );
714
+ outb (0x01 , ioBase + ssrr );
715
+ goto exit ;
716
+ }
717
+
718
+ temp = ioBase + readdata ;
719
+ if (data_len == 1 )
720
+ {
721
+ byte_data = inb (temp );
722
+ data -> byte = byte_data ;
723
+ }
724
+ else if (data_len == 2 )
725
+ {
726
+ word_data = inb (temp );
727
+ word_data |= (inb (++ temp ) << 8 );
728
+ data -> word = word_data ;
729
+ }
730
+ }
731
+ else // do i2c write
732
+ {
733
+ temp = ioBase + writedata ;
734
+ if (data_len == 1 )
735
+ {
736
+ byte_data = data -> byte ;
737
+ outb (byte_data , temp );
738
+ }
739
+ else if (data_len == 2 )
740
+ {
741
+ word_data = data -> word ;
742
+ outb ((word_data & 0xff ), temp );
743
+ outb ((word_data >> 4 ), (++ temp ));
744
+ }
745
+ // write dev addr
746
+ outb (addr , ioBase + devaddr );
747
+
748
+ // check bus access status
749
+ while ((inb (ioBase + ssrr ) & SSRR_BUS_BUSY ))
750
+ {
751
+ udelay (100 );
752
+ }
753
+
754
+ if ((inb (ioBase + ssrr ) & SSRR_MASTER_ERR ) == SSRR_MASTER_ERR ) {
755
+ /* Read error reset the port */
756
+ error = - EIO ;
757
+ outb (0x00 , ioBase + ssrr );
758
+ udelay (3000 );
759
+ outb (0x01 , ioBase + ssrr );
760
+ goto exit ;
761
+ }
762
+ }
763
+
764
+ mutex_unlock (& cpld_data -> cpld_lock );
765
+ return 0 ;
766
+
767
+ exit :
768
+ mutex_unlock (& cpld_data -> cpld_lock );
769
+ return error ;
770
+ }
771
+
772
+
613
773
static int dx010_i2c_access (struct i2c_adapter * a , u16 addr ,
614
774
unsigned short flags , char rw , u8 cmd ,
615
775
int size , union i2c_smbus_data * data )
@@ -624,39 +784,19 @@ static int dx010_i2c_access(struct i2c_adapter *a, u16 addr,
624
784
625
785
/* Map the size to what the chip understands */
626
786
switch (size ) {
627
- case I2C_SMBUS_QUICK :
628
- size = HST_CNTL2_QUICK ;
629
- break ;
630
787
case I2C_SMBUS_BYTE :
631
- size = HST_CNTL2_BYTE ;
632
- break ;
633
788
case I2C_SMBUS_BYTE_DATA :
634
- size = HST_CNTL2_BYTE_DATA ;
635
- break ;
636
789
case I2C_SMBUS_WORD_DATA :
637
- size = HST_CNTL2_WORD_DATA ;
638
- break ;
639
- case I2C_SMBUS_BLOCK_DATA :
640
- size = HST_CNTL2_BLOCK ;
641
- break ;
642
- default :
643
- dev_warn (& a -> dev , "Unsupported transaction %d\n" , size );
644
- error = - EOPNOTSUPP ;
645
- goto Done ;
646
- }
647
-
648
- switch (size ) {
649
- case HST_CNTL2_BYTE : /* Result put in SMBHSTDAT0 */
650
- break ;
651
- case HST_CNTL2_BYTE_DATA :
652
- break ;
653
- case HST_CNTL2_WORD_DATA :
654
- if ( 0 == i2c_read_eeprom (a ,addr ,new_data ,cmd ,data )){
790
+ if (0 == dx010_cpld_i2c_access (a , addr , new_data , rw , cmd , size , data )){
655
791
error = 0 ;
656
792
}else {
657
793
error = - EIO ;
658
794
}
659
795
break ;
796
+ default :
797
+ dev_warn (& a -> dev , "Unsupported transaction %d\n" , size );
798
+ error = - EOPNOTSUPP ;
799
+ goto Done ;
660
800
}
661
801
662
802
Done :
@@ -790,6 +930,6 @@ module_init(cel_dx010_lpc_init);
790
930
module_exit (cel_dx010_lpc_exit );
791
931
792
932
MODULE_AUTHOR (
"Pradchaya P <[email protected] >" );
793
- MODULE_VERSION ("1.0.1 " );
933
+ MODULE_VERSION ("1.0.2 " );
794
934
MODULE_DESCRIPTION ("Celestica SeaStone DX010 LPC Driver" );
795
- MODULE_LICENSE ("GPL" );
935
+ MODULE_LICENSE ("GPL" );
0 commit comments