Revert "[Ragile]: Add new centec platform ra-b6010 (#14819)"
This reverts commit 75062436e8
.
This commit is contained in:
parent
f6897bb585
commit
3bdfdd95ea
@ -1,868 +0,0 @@
|
||||
{
|
||||
"macleds" : {
|
||||
"polarity" : 1,
|
||||
"freq" : 2500,
|
||||
"interval" : 50000000,
|
||||
"maps" : [
|
||||
{
|
||||
"port_id" : 0,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port1/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 1,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port2/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 2,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port3/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 3,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port4/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 4,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port5/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 5,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port6/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 6,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port7/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 7,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port8/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 16,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port9/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 17,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port10/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 18,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port11/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 19,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port12/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 20,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port13/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 21,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port14/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 22,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port15/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 23,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port16/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 8,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port17/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 9,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port18/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 10,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port19/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 11,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port20/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 32,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port21/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 33,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port22/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 34,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port23/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 35,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port24/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 36,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port25/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 37,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port26/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 38,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port27/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 39,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port28/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 40,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port29/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 41,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port30/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 42,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port31/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 43,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port32/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 24,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port33/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 25,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port34/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 26,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port35/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 27,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port36/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 48,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port37/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 49,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port38/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 50,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port39/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 51,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port40/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 52,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port41/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 53,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port42/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 54,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port43/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 55,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port44/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 56,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port45/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 57,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port46/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 58,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port47/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 59,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port48/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 12,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port49/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 13,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port50/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 14,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port51/brightness"
|
||||
},
|
||||
{
|
||||
"port_id" : 15,
|
||||
"lchip" : 0,
|
||||
"ctl_id" : 0,
|
||||
"mode" : "LED_MODE_1_RXLNK_BIACT",
|
||||
"fixed" : 0,
|
||||
"sysfs_path" : "/sys/class/leds/port52/brightness"
|
||||
}
|
||||
]
|
||||
},
|
||||
"phys" : [
|
||||
{
|
||||
"macid" : 0,
|
||||
"busid" : 0,
|
||||
"addr" : 0,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 1,
|
||||
"busid" : 0,
|
||||
"addr" : 1,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 2,
|
||||
"busid" : 0,
|
||||
"addr" : 2,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 3,
|
||||
"busid" : 0,
|
||||
"addr" : 3,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 4,
|
||||
"busid" : 0,
|
||||
"addr" : 4,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 5,
|
||||
"busid" : 0,
|
||||
"addr" : 5,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 6,
|
||||
"busid" : 0,
|
||||
"addr" : 6,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 7,
|
||||
"busid" : 0,
|
||||
"addr" : 7,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 16,
|
||||
"busid" : 0,
|
||||
"addr" : 8,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 17,
|
||||
"busid" : 0,
|
||||
"addr" : 9,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 18,
|
||||
"busid" : 0,
|
||||
"addr" : 10,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 19,
|
||||
"busid" : 0,
|
||||
"addr" : 11,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 20,
|
||||
"busid" : 0,
|
||||
"addr" : 12,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 21,
|
||||
"busid" : 0,
|
||||
"addr" : 13,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 22,
|
||||
"busid" : 0,
|
||||
"addr" : 14,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 23,
|
||||
"busid" : 0,
|
||||
"addr" : 15,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 8,
|
||||
"busid" : 0,
|
||||
"addr" : 16,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 9,
|
||||
"busid" : 0,
|
||||
"addr" : 17,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 10,
|
||||
"busid" : 0,
|
||||
"addr" : 18,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 11,
|
||||
"busid" : 0,
|
||||
"addr" : 19,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 32,
|
||||
"busid" : 0,
|
||||
"addr" : 20,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 33,
|
||||
"busid" : 0,
|
||||
"addr" : 21,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 34,
|
||||
"busid" : 0,
|
||||
"addr" : 22,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 35,
|
||||
"busid" : 0,
|
||||
"addr" : 23,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 36,
|
||||
"busid" : 1,
|
||||
"addr" : 0,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 37,
|
||||
"busid" : 1,
|
||||
"addr" : 1,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 38,
|
||||
"busid" : 1,
|
||||
"addr" : 2,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 39,
|
||||
"busid" : 1,
|
||||
"addr" : 3,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 40,
|
||||
"busid" : 1,
|
||||
"addr" : 4,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 41,
|
||||
"busid" : 1,
|
||||
"addr" : 5,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 42,
|
||||
"busid" : 1,
|
||||
"addr" : 6,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 43,
|
||||
"busid" : 1,
|
||||
"addr" : 7,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 24,
|
||||
"busid" : 1,
|
||||
"addr" : 8,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 25,
|
||||
"busid" : 1,
|
||||
"addr" : 9,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 26,
|
||||
"busid" : 1,
|
||||
"addr" : 10,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 27,
|
||||
"busid" : 1,
|
||||
"addr" : 11,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 48,
|
||||
"busid" : 1,
|
||||
"addr" : 12,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 49,
|
||||
"busid" : 1,
|
||||
"addr" : 13,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 50,
|
||||
"busid" : 1,
|
||||
"addr" : 14,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 51,
|
||||
"busid" : 1,
|
||||
"addr" : 15,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 52,
|
||||
"busid" : 1,
|
||||
"addr" : 16,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 53,
|
||||
"busid" : 1,
|
||||
"addr" : 17,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 54,
|
||||
"busid" : 1,
|
||||
"addr" : 18,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 55,
|
||||
"busid" : 1,
|
||||
"addr" : 19,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 56,
|
||||
"busid" : 1,
|
||||
"addr" : 20,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 57,
|
||||
"busid" : 1,
|
||||
"addr" : 21,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 58,
|
||||
"busid" : 1,
|
||||
"addr" : 22,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
},
|
||||
{
|
||||
"macid" : 59,
|
||||
"busid" : 1,
|
||||
"addr" : 23,
|
||||
"base_port": 1,
|
||||
"last_port": 4
|
||||
}
|
||||
],
|
||||
"ffe" : {
|
||||
"board_material" : "BOARD_MATERIAL_M4",
|
||||
"config" : [
|
||||
{
|
||||
"serdes_id" : [0],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [0, 255, 10, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [1],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [0, 240, 10, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [2],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [0, 230, 10, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [3],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [0, 220, 7, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [4],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [0, 220, 8, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [5],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [0, 210, 6, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [6],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [0, 180, 6, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [7],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [0, 180, 5, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [8],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [2, 160, 4, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [9],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [2, 160, 4, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [10],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [3, 140, 9, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [11],
|
||||
"is_dac" : 0,
|
||||
"speed" : [1000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [3, 140, 5, 0]
|
||||
},
|
||||
{
|
||||
"serdes_id" : [12, 13, 14, 15],
|
||||
"is_dac" : 0,
|
||||
"speed" : [10000],
|
||||
"mode" : "CTC_CHIP_SERDES_FFE_MODE_DEFINE",
|
||||
"cfg" : [3, 94, 15, 0]
|
||||
}
|
||||
]
|
||||
},
|
||||
"ctle" : {
|
||||
"config" : [
|
||||
{
|
||||
"serdes_id" : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
||||
"auto-en" : 0,
|
||||
"cfg" : [6, 14, 2]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
#----------------- SDK Feature Support --------------
|
||||
[MPLS_SUPPORT] = 1;
|
||||
[APS_SUPPORT] = 1;
|
||||
[OAM_SUPPORT] = 1;
|
||||
[PTP_SUPPORT] = 0;
|
||||
[SYNCE_SUPPORT] = 0;
|
||||
[STACKING_SUPPORT] = 1;
|
||||
[BPE_SUPPORT] = 0;
|
||||
[IPFIX_SUPPORT] = 1;
|
||||
[MONITOR_SUPPORT] = 1;
|
||||
[OVERLAY_SUPPORT] = 1;
|
||||
[EFD_SUPPORT] = 1;
|
||||
[FCOE_SUPPORT] = 0;
|
||||
[TRILL_SUPPORT] = 0;
|
||||
[WLAN_SUPPORT] = 1;
|
||||
[NPM_SUPPORT] = 1;
|
||||
[DOT1AE_SUPPORT] = 1;
|
||||
|
||||
#----------------- Chip Init Parameter --------------
|
||||
#Local chip number and global chip id
|
||||
[Local chip_num] = 1
|
||||
[Local chip0] = 0
|
||||
[Local chip1] = 1
|
||||
|
||||
#Cut through mode 0: Disable; 1:10/40/100G; 2:1/10/100G; 3:1/10/40G; other:Flex, refer to CUT_THROUGH_BITMAP
|
||||
[CUT_THROUGH_SPEED] = 0
|
||||
#Flex cut through mode, speed enable by bitmap, refer to ctc_port_speed_t, Notice: 10M/100M/1G treat as the same speed
|
||||
[CUT_THROUGH_BITMAP] = 0
|
||||
|
||||
#Network cpu port
|
||||
[CPU_NETWORK_PORT_EN] = 0
|
||||
[CPU_NETWORK_PORT_ID] = 47
|
||||
|
||||
#Enable parity error and multi-bit ecc recover
|
||||
[ECC_RECOVER_EN] = 0
|
||||
[TCAM_SCAN_EN] = 0
|
||||
|
||||
#----------------- Interrupt Init Parameter --------------
|
||||
#0: pin, 1: msi
|
||||
[Interrupt_mode] = 0
|
||||
[IRQ] = 69
|
||||
|
||||
#----------------- NextHop Init Parameter --------------
|
||||
#0: SDK work in pizzbox (single chip system), 1: SDK work in multi-chip system
|
||||
[Nexthop Edit Mode] = 0
|
||||
[External Nexthop Number] = 16384
|
||||
[MPLS Tunnel Number] = 1024
|
||||
|
||||
#----------------- L2 Init Parameter --------------
|
||||
[FDB Hw Learning] = 1
|
||||
[Logic Port Num] = 1024
|
||||
#0: 128 instance per port, 1: 64 instance per port, 2: 32 instance per port
|
||||
[STP MODE] = 0
|
||||
[MAX_FID_NUM] = 5120
|
||||
|
||||
#----------------- Stats Init Parameter --------------
|
||||
[STATS_PORT_EN] = 0
|
||||
[STATS_ECMP_EN] = 0
|
||||
|
||||
#----------------- BPE Init Parameter --------------
|
||||
[BPE_BR_PORT_EXTENDER_EN] = 0
|
||||
[BPE_BR_UC_MAX_ECID] = 1024
|
||||
[BPE_BR_MC_MAX_ECID] = 4096
|
||||
[BPE_BR_PORT_BASE] = 0
|
||||
|
||||
#----------------- Ipuc Init Parameter --------------
|
||||
#0: tcam use prefix 16; 1: tcam use prefix 8
|
||||
[IPUC_TCAM_PREFIX_8] = 1
|
||||
|
||||
#----------------- QoS Init Parameter --------------
|
||||
#QoS policer number support 1K/2K/4K/8K, default 4K
|
||||
[QOS_POLICER_NUM] = 4096
|
||||
#QoS port queue number support 16/8/8 BPE/4 BPE,
|
||||
#When resrc_profile.cfg exist, queue number valid,
|
||||
#Default 8 queue mode
|
||||
#8 queue = 8
|
||||
#16 queue = 16
|
||||
#4 queue BPE = 17
|
||||
#8 queue BPE = 18
|
||||
[QOS_PORT_QUEUE_NUM] = 8
|
||||
#QoS port extend queue number support 0/4, default 0
|
||||
[QOS_PORT_EXT_QUEUE_NUM] = 0
|
||||
#QoS CPU reason queue number support 128/64/32, default 128
|
||||
[QOS_CPU_QUEUE_NUM] = 128
|
||||
[QOS_INGRESS_VLAN_POLICER_NUM] = 0
|
||||
[QOS_EGRESS_VLAN_POLICER_NUM] = 0
|
||||
[QOS_POLICER_MERGE_MODE] = 0
|
||||
#QOS service queue mode, default 0,0:logic scr port + dstport enq 1:service id + dstport enq
|
||||
[QOS_SERVICE_QUEUE_MODE] = 0
|
||||
#Global enable logic dst port + dstport enq
|
||||
[QOS_SERVICE_QUEUE_EGRESS_EN] = 0
|
||||
|
||||
#----------------- Stacking Init Parameter --------------
|
||||
#0: normal mode; 1: spine-leaf mode
|
||||
[FABRIC MODE] = 0
|
||||
[STACKING VERSION] = 1
|
@ -1,281 +0,0 @@
|
||||
#Generated by 'CTC DataPath Tools' on Fri Dec 18 19:15:31 2020
|
||||
#Version 1.0, Supported by TsingMa SDK
|
||||
|
||||
|
||||
#SERDES_MODE : 0-NONE, 1-XFI, 2-SGMII, 3-Not Support, 4-QSGMII, 5-XAUI, 6-DXAUI, 7-XLG, 8-CG, 9-SGMII2G5
|
||||
# 10-USXGMII-S, 11-USXGMII-M2G5, 12-USXGMII-M5G, 13-XXVG, 14-LG, 15-100BASE-FX
|
||||
#SERDES_RX_POLY: 0-Normal, 1-Inverse
|
||||
#SERDES_SWITCH : 0-Not Support Dynamic Switch, 1-Support Dynamic Switch
|
||||
|
||||
[WLAN_ENABLE] = 1
|
||||
[DOT1AE_ENABLE] = 1
|
||||
|
||||
[CORE_PLLA] = 600
|
||||
#{
|
||||
[SERDES_ITEM]
|
||||
#repeat 32 step 6
|
||||
[SERDES_ID] = 0
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 1
|
||||
[SERDES_TX_POLY] = 1
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 1
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 2
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 1
|
||||
[SERDES_TX_POLY] = 1
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 3
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 4
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 5
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 6
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 7
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 1
|
||||
[SERDES_TX_POLY] = 1
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 8
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 1
|
||||
[SERDES_TX_POLY] = 1
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 9
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 10
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 11
|
||||
[SERDES_MODE] = 4
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 12
|
||||
[SERDES_MODE] = 1
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 1
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 13
|
||||
[SERDES_MODE] = 1
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 1
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 14
|
||||
[SERDES_MODE] = 1
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 1
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 15
|
||||
[SERDES_MODE] = 1
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 1
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 16
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 17
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 18
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 19
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 20
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 21
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 22
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 23
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 24
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 25
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 26
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 1
|
||||
|
||||
[SERDES_ID] = 27
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 1
|
||||
|
||||
[SERDES_ID] = 28
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 29
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 0
|
||||
|
||||
[SERDES_ID] = 30
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 1
|
||||
|
||||
[SERDES_ID] = 31
|
||||
[SERDES_MODE] = 3
|
||||
[SERDES_RX_POLY] = 0
|
||||
[SERDES_TX_POLY] = 0
|
||||
[SERDES_SWITCH] = 0
|
||||
[SERDES_GROUP] = 1
|
||||
|
||||
#repeat end
|
||||
#}
|
||||
|
||||
|
||||
#[SERDES_TO_LPORT]
|
||||
#{
|
||||
# | QSGMII/USXGMII-M2G5 | USXGMII-M5G | USXGMII-S | 100BASE-FX | SGMII/SGMII2G5/XFI | XAUI/DXAUI | XLG | XXVG | LG | CG
|
||||
#---------|---------------------|-------------|-----------|------------|--------------------|------------|-----|------|----|---
|
||||
#serdes 0 |0 /1 /2 /3 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 1 |4 /5 /6 /7 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 2 |16/17/18/19 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 3 |20/21/22/23 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 4 |8 /9 /10/11 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 5 |32/33/34/35 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 6 |36/37/38/39 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 7 |40/41/42/43 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 8 |24/25/26/27 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 9 |48/49/50/51 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 10|52/53/54/55 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 11|56/57/58/59 |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 12|NA |NA |NA |12 |12 |12 |12 |NA |NA |NA
|
||||
#serdes 13|NA |NA |NA |13 |13 |12 |12 |NA |NA |NA
|
||||
#serdes 14|NA |NA |NA |14 |14 |12 |12 |NA |NA |NA
|
||||
#serdes 15|NA |NA |NA |15 |15 |12 |12 |NA |NA |NA
|
||||
#serdes 16|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 17|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 18|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 19|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 20|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 21|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 22|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 23|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 24|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 25|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 26|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 27|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 28|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 29|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 30|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#serdes 31|NA |NA |NA |NA |NA |NA |NA |NA |NA |NA
|
||||
#}
|
@ -1 +0,0 @@
|
||||
RA-B6010-48GT4X l1
|
@ -1,198 +0,0 @@
|
||||
#######################PHY_MAPPING_48+4#######################
|
||||
|
||||
#{
|
||||
[PHY_MAPPING_ITEM]
|
||||
|
||||
[API_PORT] = 0
|
||||
[PHY_ADDR] = 0
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 1
|
||||
[PHY_ADDR] = 1
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 2
|
||||
[PHY_ADDR] = 2
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 3
|
||||
[PHY_ADDR] = 3
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 4
|
||||
[PHY_ADDR] = 4
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 5
|
||||
[PHY_ADDR] = 5
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 6
|
||||
[PHY_ADDR] = 6
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 7
|
||||
[PHY_ADDR] = 7
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 16
|
||||
[PHY_ADDR] = 8
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 17
|
||||
[PHY_ADDR] = 9
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 18
|
||||
[PHY_ADDR] = 10
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 19
|
||||
[PHY_ADDR] = 11
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 20
|
||||
[PHY_ADDR] = 12
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 21
|
||||
[PHY_ADDR] = 13
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 22
|
||||
[PHY_ADDR] = 14
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 23
|
||||
[PHY_ADDR] = 15
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 8
|
||||
[PHY_ADDR] = 16
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 9
|
||||
[PHY_ADDR] = 17
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 10
|
||||
[PHY_ADDR] = 18
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 11
|
||||
[PHY_ADDR] = 19
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 32
|
||||
[PHY_ADDR] = 20
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 33
|
||||
[PHY_ADDR] = 21
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 34
|
||||
[PHY_ADDR] = 22
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 35
|
||||
[PHY_ADDR] = 23
|
||||
[MDIO_BUS] = 0
|
||||
|
||||
[API_PORT] = 36
|
||||
[PHY_ADDR] = 0
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 37
|
||||
[PHY_ADDR] = 1
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 38
|
||||
[PHY_ADDR] = 2
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 39
|
||||
[PHY_ADDR] = 3
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 40
|
||||
[PHY_ADDR] = 4
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 41
|
||||
[PHY_ADDR] = 5
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 42
|
||||
[PHY_ADDR] = 6
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 43
|
||||
[PHY_ADDR] = 7
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 24
|
||||
[PHY_ADDR] = 8
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 25
|
||||
[PHY_ADDR] = 9
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 26
|
||||
[PHY_ADDR] = 10
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 27
|
||||
[PHY_ADDR] = 11
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 48
|
||||
[PHY_ADDR] = 12
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 49
|
||||
[PHY_ADDR] = 13
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 50
|
||||
[PHY_ADDR] = 14
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 51
|
||||
[PHY_ADDR] = 15
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 52
|
||||
[PHY_ADDR] = 16
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 53
|
||||
[PHY_ADDR] = 17
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 54
|
||||
[PHY_ADDR] = 18
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 55
|
||||
[PHY_ADDR] = 19
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 56
|
||||
[PHY_ADDR] = 20
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 57
|
||||
[PHY_ADDR] = 21
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 58
|
||||
[PHY_ADDR] = 22
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
[API_PORT] = 59
|
||||
[PHY_ADDR] = 23
|
||||
[MDIO_BUS] = 1
|
||||
|
||||
#}
|
@ -1 +0,0 @@
|
||||
centec-arm64
|
@ -1,53 +0,0 @@
|
||||
# name lanes alias index speed admin_status
|
||||
Ethernet1 0 eth-0-1 1 1000 up
|
||||
Ethernet2 1 eth-0-2 2 1000 up
|
||||
Ethernet3 2 eth-0-3 3 1000 up
|
||||
Ethernet4 3 eth-0-4 4 1000 up
|
||||
Ethernet5 4 eth-0-5 5 1000 up
|
||||
Ethernet6 5 eth-0-6 6 1000 up
|
||||
Ethernet7 6 eth-0-7 7 1000 up
|
||||
Ethernet8 7 eth-0-8 8 1000 up
|
||||
Ethernet9 16 eth-0-9 9 1000 up
|
||||
Ethernet10 17 eth-0-10 10 1000 up
|
||||
Ethernet11 18 eth-0-11 11 1000 up
|
||||
Ethernet12 19 eth-0-12 12 1000 up
|
||||
Ethernet13 20 eth-0-13 13 1000 up
|
||||
Ethernet14 21 eth-0-14 14 1000 up
|
||||
Ethernet15 22 eth-0-15 15 1000 up
|
||||
Ethernet16 23 eth-0-16 16 1000 up
|
||||
Ethernet17 8 eth-0-17 17 1000 up
|
||||
Ethernet18 9 eth-0-18 18 1000 up
|
||||
Ethernet19 10 eth-0-19 19 1000 up
|
||||
Ethernet20 11 eth-0-20 20 1000 up
|
||||
Ethernet21 32 eth-0-21 21 1000 up
|
||||
Ethernet22 33 eth-0-22 22 1000 up
|
||||
Ethernet23 34 eth-0-23 23 1000 up
|
||||
Ethernet24 35 eth-0-24 24 1000 up
|
||||
Ethernet25 36 eth-0-25 25 1000 up
|
||||
Ethernet26 37 eth-0-26 26 1000 up
|
||||
Ethernet27 38 eth-0-27 27 1000 up
|
||||
Ethernet28 39 eth-0-28 28 1000 up
|
||||
Ethernet29 40 eth-0-29 29 1000 up
|
||||
Ethernet30 41 eth-0-30 30 1000 up
|
||||
Ethernet31 42 eth-0-31 31 1000 up
|
||||
Ethernet32 43 eth-0-32 32 1000 up
|
||||
Ethernet33 24 eth-0-33 33 1000 up
|
||||
Ethernet34 25 eth-0-34 34 1000 up
|
||||
Ethernet35 26 eth-0-35 35 1000 up
|
||||
Ethernet36 27 eth-0-36 36 1000 up
|
||||
Ethernet37 48 eth-0-37 37 1000 up
|
||||
Ethernet38 49 eth-0-38 38 1000 up
|
||||
Ethernet39 50 eth-0-39 39 1000 up
|
||||
Ethernet40 51 eth-0-40 40 1000 up
|
||||
Ethernet41 52 eth-0-41 41 1000 up
|
||||
Ethernet42 53 eth-0-42 42 1000 up
|
||||
Ethernet43 54 eth-0-43 43 1000 up
|
||||
Ethernet44 55 eth-0-44 44 1000 up
|
||||
Ethernet45 56 eth-0-45 45 1000 up
|
||||
Ethernet46 57 eth-0-46 46 1000 up
|
||||
Ethernet47 58 eth-0-47 47 1000 up
|
||||
Ethernet48 59 eth-0-48 48 1000 up
|
||||
Ethernet49 12 eth-0-49 49 10000 up
|
||||
Ethernet50 13 eth-0-50 50 10000 up
|
||||
Ethernet51 14 eth-0-51 51 10000 up
|
||||
Ethernet52 15 eth-0-52 52 10000 up
|
@ -1,4 +0,0 @@
|
||||
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-p-chip-profile.txt
|
||||
SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-p-datapath.txt
|
||||
SAI_PLATFORM_CFG_FILE=/usr/share/sonic/hwsku/RA-b6010-48gt4x-board.json
|
||||
SAI_PHY_DRIVER_PATH=/usr/share/sonic/hwsku/phy_drv
|
@ -1,48 +0,0 @@
|
||||
|
||||
chip set serdes 0 ffe mode user-define c0 0 c1 255 c2 10 c3 0 c4 0
|
||||
chip set serdes 1 ffe mode user-define c0 0 c1 240 c2 10 c3 0 c4 0
|
||||
chip set serdes 2 ffe mode user-define c0 0 c1 230 c2 10 c3 0 c4 0
|
||||
chip set serdes 3 ffe mode user-define c0 0 c1 220 c2 7 c3 0 c4 0
|
||||
chip set serdes 4 ffe mode user-define c0 0 c1 220 c2 8 c3 0 c4 0
|
||||
chip set serdes 5 ffe mode user-define c0 0 c1 210 c2 6 c3 0 c4 0
|
||||
chip set serdes 6 ffe mode user-define c0 0 c1 180 c2 6 c3 0 c4 0
|
||||
chip set serdes 7 ffe mode user-define c0 0 c1 180 c2 5 c3 0 c4 0
|
||||
chip set serdes 8 ffe mode user-define c0 2 c1 160 c2 4 c3 0 c4 0
|
||||
chip set serdes 9 ffe mode user-define c0 2 c1 160 c2 4 c3 0 c4 0
|
||||
chip set serdes 10 ffe mode user-define c0 3 c1 140 c2 9 c3 0 c4 0
|
||||
chip set serdes 11 ffe mode user-define c0 3 c1 140 c2 5 c3 0 c4 0
|
||||
chip set serdes 12 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0
|
||||
chip set serdes 13 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0
|
||||
chip set serdes 14 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0
|
||||
chip set serdes 15 ffe mode user-define c0 3 c1 94 c2 15 c3 0 c4 0
|
||||
|
||||
|
||||
chip set serdes 0 ctle 6 14 2
|
||||
chip set serdes 1 ctle 6 14 2
|
||||
chip set serdes 2 ctle 6 14 2
|
||||
chip set serdes 3 ctle 6 14 2
|
||||
chip set serdes 4 ctle 6 14 2
|
||||
chip set serdes 5 ctle 6 14 2
|
||||
chip set serdes 6 ctle 6 14 2
|
||||
chip set serdes 7 ctle 6 14 2
|
||||
chip set serdes 8 ctle 6 14 2
|
||||
chip set serdes 9 ctle 6 14 2
|
||||
chip set serdes 10 ctle 6 14 2
|
||||
chip set serdes 11 ctle 6 14 2
|
||||
|
||||
|
||||
|
||||
# rtk eye param, post_amp|main_amp|pre_amp
|
||||
port 0 phy-attr type 2001 value 0x1c1e00
|
||||
port 4 phy-attr type 2001 value 0x101600
|
||||
port 16 phy-attr type 2001 value 0x111500
|
||||
port 20 phy-attr type 2001 value 0x0e1100
|
||||
port 8 phy-attr type 2001 value 0x0f1000
|
||||
port 32 phy-attr type 2001 value 0x0e0f00
|
||||
port 36 phy-attr type 2001 value 0x0a0a00
|
||||
port 40 phy-attr type 2001 value 0x0a0900
|
||||
port 24 phy-attr type 2001 value 0x000c00
|
||||
port 48 phy-attr type 2001 value 0x000b00
|
||||
port 52 phy-attr type 2001 value 0x000b00
|
||||
port 56 phy-attr type 2001 value 0x000a00
|
||||
|
@ -1 +0,0 @@
|
||||
RA-B6010-48GT4X l1
|
@ -1,9 +0,0 @@
|
||||
CONSOLE_SPEED=115200
|
||||
|
||||
#fix env
|
||||
config_env(){
|
||||
dd if=/dev/mtd1 of=env.bin
|
||||
flashcp -v env.bin /dev/mtd4
|
||||
}
|
||||
trap_push "config_env || true"
|
||||
|
@ -1,173 +0,0 @@
|
||||
{
|
||||
"chassis": {
|
||||
"name": "RA-B6010-48GT4X",
|
||||
"thermal_manager": false,
|
||||
"status_led": {
|
||||
"controllable": false,
|
||||
"colors": ["green", "blinking_green", "amber", "blinking_amber"]
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"name": "CPU CPLD"
|
||||
},
|
||||
{
|
||||
"name": "MAC1 CPLD"
|
||||
}
|
||||
],
|
||||
"fans": [
|
||||
{
|
||||
"name": "Fantray1_1",
|
||||
"speed": {
|
||||
"controllable": true,
|
||||
"minimum": 30,
|
||||
"maximum": 99
|
||||
},
|
||||
"status_led": {
|
||||
"available": false,
|
||||
"colors": ["off", "red", "amber", "green"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Fantray2_1",
|
||||
"speed": {
|
||||
"controllable": true,
|
||||
"minimum": 30,
|
||||
"maximum": 99
|
||||
},
|
||||
"status_led": {
|
||||
"available": false,
|
||||
"colors": ["off", "red", "amber", "green"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"fan_drawers":[
|
||||
{
|
||||
"name": "Fantray1",
|
||||
"num_fans" : 1,
|
||||
"status_led": {
|
||||
"controllable": false,
|
||||
"colors": ["amber", "green", "off"]
|
||||
},
|
||||
"fans": [
|
||||
{
|
||||
"name": "FanTray1_1",
|
||||
"speed": {
|
||||
"controllable": true,
|
||||
"minimum": 30,
|
||||
"maximum": 99
|
||||
},
|
||||
"status_led": {
|
||||
"available": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Fantray2",
|
||||
"num_fans" : 1,
|
||||
"status_led": {
|
||||
"controllable": false,
|
||||
"colors": ["amber", "green", "off"]
|
||||
},
|
||||
"fans": [
|
||||
{
|
||||
"name": "FanTray2_1",
|
||||
"speed": {
|
||||
"controllable": true,
|
||||
"minimum": 30,
|
||||
"maximum": 99
|
||||
},
|
||||
"status_led": {
|
||||
"available": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"psus": [
|
||||
{
|
||||
"name": "PSU 1",
|
||||
"voltage": true,
|
||||
"current": true,
|
||||
"power": true,
|
||||
"max_power": false,
|
||||
"voltage_high_threshold": true,
|
||||
"voltage_low_threshold": true,
|
||||
"temperature": true,
|
||||
"fans_target_speed": false,
|
||||
"status_led": {
|
||||
"controllable": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "PSU 2",
|
||||
"voltage": true,
|
||||
"current": true,
|
||||
"power": true,
|
||||
"max_power": false,
|
||||
"voltage_high_threshold": true,
|
||||
"voltage_low_threshold": true,
|
||||
"temperature": true,
|
||||
"fans_target_speed": false,
|
||||
"status_led": {
|
||||
"controllable": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"thermals": [
|
||||
{
|
||||
"name": "ASIC_TEMP",
|
||||
"controllable": false,
|
||||
"low-crit-threshold": true,
|
||||
"high-crit-threshold": true,
|
||||
"low-threshold": true,
|
||||
"high-threshold": true,
|
||||
"minimum-recorded": true,
|
||||
"maximum-recorded": true
|
||||
},
|
||||
{
|
||||
"name": "CPU_TEMP",
|
||||
"controllable": false,
|
||||
"low-crit-threshold": true,
|
||||
"high-crit-threshold": true,
|
||||
"low-threshold": true,
|
||||
"high-threshold": true,
|
||||
"minimum-recorded": true,
|
||||
"maximum-recorded": true
|
||||
},
|
||||
{
|
||||
"name": "INLET_TEMP",
|
||||
"controllable": false,
|
||||
"low-crit-threshold": true,
|
||||
"high-crit-threshold": true,
|
||||
"low-threshold": true,
|
||||
"high-threshold": true,
|
||||
"minimum-recorded": true,
|
||||
"maximum-recorded": true
|
||||
},
|
||||
{
|
||||
"name": "OUTLET_TEMP",
|
||||
"controllable": false,
|
||||
"low-crit-threshold": true,
|
||||
"high-crit-threshold": true,
|
||||
"low-threshold": true,
|
||||
"high-threshold": true,
|
||||
"minimum-recorded": true,
|
||||
"maximum-recorded": true
|
||||
},
|
||||
{
|
||||
"name": "TPS53688_TEMP",
|
||||
"controllable": false,
|
||||
"low-crit-threshold": true,
|
||||
"high-crit-threshold": true,
|
||||
"low-threshold": true,
|
||||
"high-threshold": true,
|
||||
"minimum-recorded": true,
|
||||
"maximum-recorded": true
|
||||
}
|
||||
],
|
||||
"modules": [],
|
||||
"sfps": []
|
||||
},
|
||||
"interfaces": {}
|
||||
}
|
@ -1 +0,0 @@
|
||||
centec-arm64
|
@ -1,22 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
RAGILE_CARDID = 0x00004099
|
||||
RAGILE_PRODUCTNAME = "RA-B6010-48GT4X"
|
||||
RAGILE_PART_NUMBER = "RJ000001"
|
||||
RAGILE_LABEL_REVISION = "R01"
|
||||
RAGILE_ONIE_VERSION = "2018.02"
|
||||
RAGILE_MAC_SIZE = 3
|
||||
RAGILE_MANUF_NAME = "Ragile"
|
||||
RAGILE_MANUF_COUNTRY = "CHN"
|
||||
RAGILE_VENDOR_NAME = "Ragile"
|
||||
RAGILE_DIAG_VERSION = "0.1.0.15"
|
||||
RAGILE_SERVICE_TAG = "www.ragile.com"
|
||||
|
||||
CPUEEPROMS = {"name":"cpueeprom","bus":5,"loc":0x57,"E2PRODUCT":'2', "E2TYPE":'4'}
|
||||
|
||||
# rg_eeprom = "1-0056/eeprom"
|
||||
E2_LOC = {"bus":1, "devno":0x56}
|
||||
E2_PROTECT = {}
|
||||
FAN_PROTECT = {"bus":1, "devno":0x0d, "addr":0x19, "open":0x00, "close":0xff}
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
try:
|
||||
import exceptions
|
||||
import binascii
|
||||
import time
|
||||
import optparse
|
||||
import warnings
|
||||
import os
|
||||
import sys
|
||||
from sonic_eeprom import eeprom_base
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
except ImportError, e:
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
|
||||
class board(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
|
||||
def __init__(self, name, path, cpld_root, ro):
|
||||
self.eeprom_path = "/sys/bus/i2c/devices/1-0056/eeprom"
|
||||
super(board, self).__init__(self.eeprom_path, 0, '', True)
|
@ -1,455 +0,0 @@
|
||||
# sfputil.py
|
||||
#
|
||||
# Platform-specific SFP transceiver interface for SONiC
|
||||
#
|
||||
|
||||
try:
|
||||
import time
|
||||
import subprocess
|
||||
import re
|
||||
import os
|
||||
import threading
|
||||
from sonic_sfp.sfputilbase import SfpUtilBase
|
||||
except ImportError as e:
|
||||
raise ImportError("%s - required module not found" % str(e))
|
||||
|
||||
|
||||
class SfpUtil(SfpUtilBase):
|
||||
"""Platform-specific SfpUtil class"""
|
||||
|
||||
PORT_START = 49
|
||||
PORT_END = 52
|
||||
PORTS_IN_BLOCK = 53
|
||||
EEPROM_OFFSET = 9
|
||||
SFP_DEVICE_TYPE = "optoe2"
|
||||
QSFP_DEVICE_TYPE = "optoe1"
|
||||
I2C_MAX_ATTEMPT = 3
|
||||
|
||||
SFP_STATUS_INSERTED = '1'
|
||||
SFP_STATUS_REMOVED = '0'
|
||||
|
||||
TXWRT_PROTECT = 0X4E
|
||||
TXWRT_NO_PROTECT = 0X59
|
||||
|
||||
_port_to_eeprom_mapping = {}
|
||||
port_to_i2cbus_mapping ={}
|
||||
port_dict = {}
|
||||
port_presence_info = {}
|
||||
port_reset_info = {}
|
||||
port_txdis_info = {}
|
||||
port_txwrt_info = {}
|
||||
port_led_info = {}
|
||||
|
||||
port_rxlos_info = {}
|
||||
port_txfault_info = {}
|
||||
port_drop_info = {}
|
||||
|
||||
@property
|
||||
def port_start(self):
|
||||
return self.PORT_START
|
||||
|
||||
@property
|
||||
def port_end(self):
|
||||
return self.PORT_END
|
||||
|
||||
@property
|
||||
def sfp_ports(self):
|
||||
return list(range(self.PORT_START, self.PORTS_IN_BLOCK))
|
||||
|
||||
@property
|
||||
def qsfp_ports(self):
|
||||
return []
|
||||
|
||||
@property
|
||||
def port_to_eeprom_mapping(self):
|
||||
return self._port_to_eeprom_mapping
|
||||
|
||||
def __init__(self):
|
||||
for x in range(self.PORT_START, self.PORTS_IN_BLOCK):
|
||||
self.port_to_i2cbus_mapping[x] = (x - self.PORT_START + self.EEPROM_OFFSET)
|
||||
self.port_presence_info["/sys/bus/i2c/devices/3-0030/sfp_presence1"] = [49, 50, 51, 52]
|
||||
self.port_txdis_info["/sys/bus/i2c/devices/3-0030/tx_disable"] = [49, 50, 51, 52]
|
||||
self.port_txwrt_info["/sys/bus/i2c/devices/3-0030/tx_write_protect"] = [49, 50, 51, 52]
|
||||
|
||||
# bit 1: los
|
||||
self.port_rxlos_info["/sys/bus/i2c/devices/3-0030/sfp_rx_loss1"] = [49, 50, 51, 52]
|
||||
|
||||
# bit 1: fault
|
||||
self.port_txfault_info["/sys/bus/i2c/devices/3-0030/sfp_tx_fault1"] = [49, 50, 51, 52]
|
||||
|
||||
# bit 1: drop
|
||||
self.port_drop_info["/sys/bus/i2c/devices/3-0030/sfp_drop_record1"] = [49, 50, 51, 52]
|
||||
|
||||
SfpUtilBase.__init__(self)
|
||||
|
||||
def _sfp_read_file_path(self, file_path, offset, num_bytes):
|
||||
attempts = 0
|
||||
while attempts < self.I2C_MAX_ATTEMPT:
|
||||
try:
|
||||
file_path.seek(offset)
|
||||
read_buf = file_path.read(num_bytes)
|
||||
except:
|
||||
attempts += 1
|
||||
time.sleep(0.05)
|
||||
else:
|
||||
return True, read_buf
|
||||
return False, None
|
||||
|
||||
def _sfp_eeprom_present(self, sysfs_sfp_i2c_client_eeprompath, offset):
|
||||
"""Tries to read the eeprom file to determine if the
|
||||
device/sfp is present or not. If sfp present, the read returns
|
||||
valid bytes. If not, read returns error 'Connection timed out"""
|
||||
|
||||
if not os.path.exists(sysfs_sfp_i2c_client_eeprompath):
|
||||
return False
|
||||
else:
|
||||
with open(sysfs_sfp_i2c_client_eeprompath, "rb", buffering=0) as sysfsfile:
|
||||
rv, buf = self._sfp_read_file_path(sysfsfile, offset, 1)
|
||||
return rv
|
||||
|
||||
def _add_new_sfp_device(self, sysfs_sfp_i2c_adapter_path, devaddr, devtype):
|
||||
try:
|
||||
sysfs_nd_path = "%s/new_device" % sysfs_sfp_i2c_adapter_path
|
||||
|
||||
# Write device address to new_device file
|
||||
nd_file = open(sysfs_nd_path, "w")
|
||||
nd_str = "%s %s" % (devtype, hex(devaddr))
|
||||
nd_file.write(nd_str)
|
||||
nd_file.close()
|
||||
|
||||
except Exception as err:
|
||||
print(("Error writing to new device file: %s" % str(err)))
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def _get_port_eeprom_path(self, port_num, devid):
|
||||
sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter"
|
||||
|
||||
if port_num in list(self.port_to_eeprom_mapping.keys()):
|
||||
sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[port_num]
|
||||
else:
|
||||
sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter"
|
||||
|
||||
i2c_adapter_id = self._get_port_i2c_adapter_id(port_num)
|
||||
if i2c_adapter_id is None:
|
||||
print("Error getting i2c bus num")
|
||||
return None
|
||||
|
||||
# Get i2c virtual bus path for the sfp
|
||||
sysfs_sfp_i2c_adapter_path = "%s/i2c-%s" % (sysfs_i2c_adapter_base_path,
|
||||
str(i2c_adapter_id))
|
||||
|
||||
# If i2c bus for port does not exist
|
||||
if not os.path.exists(sysfs_sfp_i2c_adapter_path):
|
||||
print(("Could not find i2c bus %s. Driver not loaded?" % sysfs_sfp_i2c_adapter_path))
|
||||
return None
|
||||
|
||||
sysfs_sfp_i2c_client_path = "%s/%s-00%s" % (sysfs_sfp_i2c_adapter_path,
|
||||
str(i2c_adapter_id),
|
||||
hex(devid)[-2:])
|
||||
|
||||
# If sfp device is not present on bus, Add it
|
||||
if not os.path.exists(sysfs_sfp_i2c_client_path):
|
||||
if port_num in self.qsfp_ports:
|
||||
ret = self._add_new_sfp_device(
|
||||
sysfs_sfp_i2c_adapter_path, devid, self.QSFP_DEVICE_TYPE)
|
||||
else:
|
||||
ret = self._add_new_sfp_device(
|
||||
sysfs_sfp_i2c_adapter_path, devid, self.SFP_DEVICE_TYPE)
|
||||
if ret != 0:
|
||||
print("Error adding sfp device")
|
||||
return None
|
||||
|
||||
sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path
|
||||
return sysfs_sfp_i2c_client_eeprom_path
|
||||
|
||||
def _read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes):
|
||||
eeprom_raw = []
|
||||
for i in range(0, num_bytes):
|
||||
eeprom_raw.append("0x00")
|
||||
|
||||
rv, raw = self._sfp_read_file_path(sysfsfile_eeprom, offset, num_bytes)
|
||||
if rv == False:
|
||||
return None
|
||||
|
||||
try:
|
||||
if isinstance(raw, str):
|
||||
for n in range(0, num_bytes):
|
||||
eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
|
||||
else:
|
||||
for n in range(0, num_bytes):
|
||||
eeprom_raw[n] = hex(raw[n])[2:].zfill(2)
|
||||
except Exception as err:
|
||||
return None
|
||||
return eeprom_raw
|
||||
|
||||
def get_eeprom_dom_raw(self, port_num):
|
||||
if port_num in self.qsfp_ports:
|
||||
# QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw
|
||||
return None
|
||||
else:
|
||||
# Read dom eeprom at addr 0x51
|
||||
return self._read_eeprom_devid(port_num, self.IDENTITY_EEPROM_ADDR, 256)
|
||||
|
||||
def get_presence(self, port_num):
|
||||
# Check for invalid port_num
|
||||
if port_num < self.port_start or port_num > self.port_end:
|
||||
return False
|
||||
|
||||
presence_path = None
|
||||
for presence_key in self.port_presence_info:
|
||||
if port_num in self.port_presence_info[presence_key]:
|
||||
presence_path = presence_key
|
||||
presence_offset = self.port_presence_info[presence_key].index(port_num)
|
||||
break
|
||||
if presence_path == None:
|
||||
return False
|
||||
|
||||
try:
|
||||
data = open(presence_path, "rb")
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
presence_data = data.read(2)
|
||||
if presence_data == "":
|
||||
return False
|
||||
result = int(presence_data, 16)
|
||||
data.close()
|
||||
|
||||
# ModPrsL is active low
|
||||
if result & (1 << presence_offset) == 0:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_low_power_mode(self, port_num):
|
||||
return False
|
||||
|
||||
def set_low_power_mode(self, port_num, lpmode):
|
||||
return False
|
||||
|
||||
def reset(self, port_num):
|
||||
return False
|
||||
|
||||
def reset_all(self):
|
||||
return False
|
||||
|
||||
def _do_write_file(self, file_handle, offset, value):
|
||||
file_handle.seek(offset)
|
||||
file_handle.write(hex(value))
|
||||
|
||||
def get_transceiver_change_event(self, timeout=0):
|
||||
|
||||
start_time = time.time()
|
||||
currernt_port_dict = {}
|
||||
forever = False
|
||||
|
||||
if timeout == 0:
|
||||
forever = True
|
||||
elif timeout > 0:
|
||||
timeout = timeout / float(1000) # Convert to secs
|
||||
else:
|
||||
print(("get_transceiver_change_event:Invalid timeout value", timeout))
|
||||
return False, {}
|
||||
|
||||
end_time = start_time + timeout
|
||||
if start_time > end_time:
|
||||
print(('get_transceiver_change_event:' \
|
||||
'time wrap / invalid timeout value', timeout))
|
||||
|
||||
return False, {} # Time wrap or possibly incorrect timeout
|
||||
|
||||
while timeout >= 0:
|
||||
# Check for OIR events and return updated port_dict
|
||||
for x in range(self.PORT_START, self.PORTS_IN_BLOCK):
|
||||
if self.get_presence(x):
|
||||
currernt_port_dict[x] = self.SFP_STATUS_INSERTED
|
||||
else:
|
||||
currernt_port_dict[x] = self.SFP_STATUS_REMOVED
|
||||
if (currernt_port_dict == self.port_dict):
|
||||
if forever:
|
||||
time.sleep(1)
|
||||
else:
|
||||
timeout = end_time - time.time()
|
||||
if timeout >= 1:
|
||||
time.sleep(1) # We poll at 1 second granularity
|
||||
else:
|
||||
if timeout > 0:
|
||||
time.sleep(timeout)
|
||||
return True, {}
|
||||
else:
|
||||
# Update reg value
|
||||
self.port_dict = currernt_port_dict
|
||||
return True, self.port_dict
|
||||
print ("get_transceiver_change_event: Should not reach here.")
|
||||
return False, {}
|
||||
|
||||
def tx_disable(self, port_num, disable):
|
||||
if not self.get_presence(port_num):
|
||||
return False
|
||||
|
||||
if port_num in self.sfp_ports:
|
||||
txwrt_path = None
|
||||
txdis_path = None
|
||||
txdis_offset = 0
|
||||
|
||||
for key in self.port_txwrt_info:
|
||||
if port_num in self.port_txwrt_info[key]:
|
||||
txwrt_path = key
|
||||
break
|
||||
if txwrt_path == None:
|
||||
return False
|
||||
|
||||
for key in self.port_txdis_info:
|
||||
if port_num in self.port_txdis_info[key]:
|
||||
txdis_path = key
|
||||
txdis_offset = self.port_txdis_info[key].index(port_num)
|
||||
break
|
||||
if txdis_path == None:
|
||||
return False
|
||||
|
||||
|
||||
try:
|
||||
with open(txwrt_path, "r+") as sys_file:
|
||||
sres = hex(self.TXWRT_NO_PROTECT)[2:]
|
||||
sys_file.write(sres)
|
||||
|
||||
with open(txdis_path, "r+") as sys_file:
|
||||
txdis_data = sys_file.read(2)
|
||||
if not txdis_data:
|
||||
return False
|
||||
result = int(txdis_data, 16)
|
||||
if disable:
|
||||
result = result | (1 << txdis_offset)
|
||||
else:
|
||||
result = result & (~(1 << txdis_offset))
|
||||
sys_file.seek(0)
|
||||
sres = hex(result)[2:]
|
||||
print(result,sres)
|
||||
sys_file.write(sres)
|
||||
|
||||
with open(txwrt_path, "r+") as sys_file:
|
||||
sres = hex(self.TXWRT_PROTECT)[2:]
|
||||
sys_file.write(sres)
|
||||
except Exception as err:
|
||||
print(err)
|
||||
return False
|
||||
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
########### sysdiag ###########
|
||||
def _get_cpld_info(self, port_num, info):
|
||||
path = None
|
||||
offset = 0
|
||||
for key in info:
|
||||
if port_num in info[key]:
|
||||
path = key
|
||||
offset = info[key].index(port_num)
|
||||
break
|
||||
return path, offset
|
||||
|
||||
def get_tx_disable(self, port_num):
|
||||
# cur only support sfp moudle
|
||||
if port_num not in self.sfp_ports:
|
||||
return False
|
||||
|
||||
if not self.get_presence(port_num):
|
||||
return False
|
||||
|
||||
path, offset = self._get_cpld_info(port_num, self.port_txdis_info)
|
||||
if path == None:
|
||||
return False
|
||||
|
||||
result = 0
|
||||
try:
|
||||
with open(path, "r") as sys_file:
|
||||
data = sys_file.read(2)
|
||||
result = int(data, 16)
|
||||
except Exception as e:
|
||||
print((str(e)))
|
||||
return False
|
||||
|
||||
# 1: disable
|
||||
if result & (1 << offset):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_rx_los(self, port_num):
|
||||
# cur only support sfp moudle
|
||||
if port_num not in self.sfp_ports:
|
||||
return False
|
||||
|
||||
path, offset = self._get_cpld_info(port_num, self.port_rxlos_info)
|
||||
if path == None:
|
||||
return False
|
||||
|
||||
result = 0
|
||||
try:
|
||||
with open(path, "r") as sys_file:
|
||||
data = sys_file.read(2)
|
||||
result = int(data, 16)
|
||||
except Exception as e:
|
||||
print((str(e)))
|
||||
return False
|
||||
|
||||
# 1: los
|
||||
if result & (1 << offset):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_tx_fault(self, port_num):
|
||||
# cur only support sfp moudle
|
||||
if port_num not in self.sfp_ports:
|
||||
return False
|
||||
|
||||
if not self.get_presence(port_num):
|
||||
return False
|
||||
|
||||
path, offset = self._get_cpld_info(port_num, self.port_txfault_info)
|
||||
if path == None:
|
||||
return False
|
||||
|
||||
result = 0
|
||||
try:
|
||||
with open(path, "r") as sys_file:
|
||||
data = sys_file.read(2)
|
||||
result = int(data, 16)
|
||||
except Exception as e:
|
||||
print((str(e)))
|
||||
return False
|
||||
|
||||
# 1: fault
|
||||
if result & (1 << offset):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
def get_plug_record(self, port_num):
|
||||
if not self.get_presence(port_num):
|
||||
return False
|
||||
|
||||
path, offset = self._get_cpld_info(port_num, self.port_drop_info)
|
||||
if path == None:
|
||||
return False
|
||||
|
||||
result = 0
|
||||
try:
|
||||
with open(path, "r") as sys_file:
|
||||
data = sys_file.read(2)
|
||||
result = int(data, 16)
|
||||
except Exception as e:
|
||||
print((str(e)))
|
||||
return False
|
||||
|
||||
# 1: drop
|
||||
if result & (1 << offset):
|
||||
return True
|
||||
else:
|
||||
return False
|
@ -1,112 +0,0 @@
|
||||
#
|
||||
# ssd_util.py
|
||||
#
|
||||
# Generic implementation of the SSD health API
|
||||
# SSD models supported:
|
||||
# - InnoDisk
|
||||
# - StorFly
|
||||
# - Virtium
|
||||
|
||||
try:
|
||||
import subprocess
|
||||
from sonic_platform_base.sonic_ssd.ssd_base import SsdBase
|
||||
except ImportError as e:
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
HEALTH_CMD = "cat /sys/kernel/debug/mmc0/mmc0:0001/ext_csd | cut -c 537-538"
|
||||
SERIAL_CMD = "cat /sys/bus/mmc/devices/mmc0\\:0001/serial"
|
||||
FIRMWARE_CMD = "cat /sys/kernel/debug/mmc0/mmc0:0001/ext_csd | cut -c 509-522"
|
||||
NOT_AVAILABLE = "N/A"
|
||||
|
||||
class SsdUtil(SsdBase):
|
||||
"""
|
||||
Generic implementation of the SSD health API
|
||||
"""
|
||||
def __init__(self, diskdev):
|
||||
self.model = "KLMCG4JETD-B041"
|
||||
self.temperature = NOT_AVAILABLE
|
||||
self.vendor_ssd_info = "====No vendor information===="
|
||||
self.health_list = [100,90,80,70,60,50,40,30,20,10,0]
|
||||
try:
|
||||
life_time = self._execute_shell(HEALTH_CMD)
|
||||
if int(life_time) in range(1,12):
|
||||
self.health = self.health_list[int(life_time) - 1]
|
||||
else:
|
||||
self.health = NOT_AVAILABLE
|
||||
except Exception as e:
|
||||
self.health = NOT_AVAILABLE
|
||||
|
||||
try:
|
||||
self.firmware = self._execute_shell(FIRMWARE_CMD)
|
||||
except Exception as e:
|
||||
self.firmware = NOT_AVAILABLE
|
||||
|
||||
try:
|
||||
serial = self._execute_shell(SERIAL_CMD)
|
||||
self.serial = serial.replace("0x",'')
|
||||
except Exception as e:
|
||||
self.serial = NOT_AVAILABLE
|
||||
|
||||
def _execute_shell(self, cmd):
|
||||
status, output = subprocess.getstatusoutput(cmd)
|
||||
if status:
|
||||
return None
|
||||
|
||||
return output
|
||||
|
||||
def get_health(self):
|
||||
"""
|
||||
Retrieves current disk health in percentages
|
||||
|
||||
Returns:
|
||||
A float number of current ssd health
|
||||
e.g. 83.5
|
||||
"""
|
||||
return self.health
|
||||
|
||||
def get_temperature(self):
|
||||
"""
|
||||
Retrieves current disk temperature in Celsius
|
||||
|
||||
Returns:
|
||||
A float number of current temperature in Celsius
|
||||
e.g. 40.1
|
||||
"""
|
||||
return self.temperature
|
||||
|
||||
def get_model(self):
|
||||
"""
|
||||
Retrieves model for the given disk device
|
||||
|
||||
Returns:
|
||||
A string holding disk model as provided by the manufacturer
|
||||
"""
|
||||
return self.model
|
||||
|
||||
def get_firmware(self):
|
||||
"""
|
||||
Retrieves firmware version for the given disk device
|
||||
|
||||
Returns:
|
||||
A string holding disk firmware version as provided by the manufacturer
|
||||
"""
|
||||
return self.firmware
|
||||
|
||||
def get_serial(self):
|
||||
"""
|
||||
Retrieves serial number for the given disk device
|
||||
|
||||
Returns:
|
||||
A string holding disk serial number as provided by the manufacturer
|
||||
"""
|
||||
return self.serial
|
||||
|
||||
def get_vendor_output(self):
|
||||
"""
|
||||
Retrieves vendor specific data for the given disk device
|
||||
|
||||
Returns:
|
||||
A string holding some vendor specific disk information
|
||||
"""
|
||||
return self.vendor_ssd_info
|
||||
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"skip_ledd": true,
|
||||
"skip_xcvrd": false,
|
||||
"skip_syseepromd": false,
|
||||
"skip_thermalctld": false,
|
||||
"skip_psud": false
|
||||
}
|
@ -11,9 +11,8 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2C_PLATFORM_MODULE)
|
||||
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48S4X_PLATFORM_MODULE)
|
||||
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2Q_PLATFORM_MODULE)
|
||||
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(FS_S5800_48T4S_PLATFORM_MODULE)
|
||||
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(RA_B6010_48GT4X_PLATFORM_MODULE)
|
||||
|
||||
ifeq ($(INSTALL_DEBUG_TOOLS),y)
|
||||
ifeq ($(INSTALL_DEBUG_TOOLS),y)
|
||||
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)
|
||||
$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES))
|
||||
else
|
||||
|
@ -1,9 +0,0 @@
|
||||
MPATH := $($(RA_B6010_48GT4X_PLATFORM_MODULE)_SRC_PATH)
|
||||
DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/centec-arm64/platform-modules-ragile.mk platform/centec-arm64/platform-modules-ragile.dep
|
||||
DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST)
|
||||
DEP_FILES += $(addprefix $(MPATH)/,$(shell cd $(MPATH) && git ls-files))
|
||||
|
||||
$(RA_B6010_48GT4X_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA
|
||||
$(RA_B6010_48GT4X_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
|
||||
$(RA_B6010_48GT4X_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES)
|
||||
|
@ -1,10 +0,0 @@
|
||||
## RA-B6010-48GT4X
|
||||
RA_B6010_48GT4X_PLATFORM_MODULE_VERSION =1.3
|
||||
export RA_B6010_48GT4X_PLATFORM_MODULE_VERSION
|
||||
|
||||
RA_B6010_48GT4X_PLATFORM_MODULE = platform-modules-ra-b6010-48gt4x_$(RA_B6010_48GT4X_PLATFORM_MODULE_VERSION)_arm64.deb
|
||||
|
||||
$(RA_B6010_48GT4X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ragile
|
||||
$(RA_B6010_48GT4X_PLATFORM_MODULE)_PLATFORM = arm64-ragile_ra-b6010-48gt4x-r0
|
||||
$(RA_B6010_48GT4X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
|
||||
SONIC_DPKG_DEBS += $(RA_B6010_48GT4X_PLATFORM_MODULE)
|
@ -7,7 +7,6 @@ include $(PLATFORM_PATH)/libsaithrift-dev.mk
|
||||
include $(PLATFORM_PATH)/tsingma-bsp.mk
|
||||
include $(PLATFORM_PATH)/platform-modules-centec-e530.mk
|
||||
include $(PLATFORM_PATH)/platform-modules-fs.mk
|
||||
include $(PLATFORM_PATH)/platform-modules-ragile.mk
|
||||
|
||||
SONIC_ALL += $(SONIC_ONE_IMAGE) \
|
||||
$(DOCKER_FPM)
|
||||
|
@ -1,15 +0,0 @@
|
||||
Copyright (C) 2019 Centec, Inc
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
@ -1 +0,0 @@
|
||||
platform drivers for Centec E530 for the SONiC project
|
@ -1,47 +0,0 @@
|
||||
PWD = $(shell pwd)
|
||||
CC ?=gcc
|
||||
INSTALL_MOD_DIR ?=extra
|
||||
KVERSION ?= $(shell uname -r)
|
||||
KERNEL_SRC ?= /lib/modules/$(KVERSION)
|
||||
EXTRA_CFLAGS:= -I$(M)/include
|
||||
EXTRA_CFLAGS+= -Wall
|
||||
ifdef ENABLE_GCOV
|
||||
ifeq ($(ENABLE_GCOV), y)
|
||||
EXTRA_CFLAGS+= -fprofile-arcs -ftest-coverage -lgcov
|
||||
endif
|
||||
endif # ENABLE_GCOV
|
||||
SUB_BUILD_DIR = $(PWD)/build
|
||||
DIR_KERNEL_SRC = $(PWD)/modules
|
||||
SCRIPT_DIR = $(PWD)/script
|
||||
SERVICE_DIR = $(PWD)/service
|
||||
BLACK_DRIVER_CONF_DIR = $(PWD)/modprobe_conf
|
||||
|
||||
app_dir = $(PWD)/app
|
||||
app_build_dir = $(app_dir)/build
|
||||
modules_build_dir = $(DIR_KERNEL_SRC)/build
|
||||
|
||||
INSTALL_MODULE_DIR = $(SUB_BUILD_DIR)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR)
|
||||
INSTALL_SCRIPT_DIR = $(SUB_BUILD_DIR)/usr/local/bin
|
||||
INSTALL_SERVICE_DIR = $(SUB_BUILD_DIR)/lib/systemd/system
|
||||
INSTALL_LIB_DIR = $(SUB_BUILD_DIR)/usr/lib/python3.9/dist-packages
|
||||
INSTALL_BLACK_DRIVER = $(SUB_BUILD_DIR)/etc/modprobe.d
|
||||
CTC_48GT4X_PHY_DIR = $(SUB_BUILD_DIR)/usr/share/sonic/device/arm64-ragile_ra-b6010-48gt4x-r0/RA-B6010-48GT4X
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(app_dir)
|
||||
$(MAKE) -C $(DIR_KERNEL_SRC)
|
||||
@if [ ! -d ${INSTALL_MODULE_DIR} ]; then mkdir -p ${INSTALL_MODULE_DIR} ;fi
|
||||
@if [ ! -d ${INSTALL_SCRIPT_DIR} ]; then mkdir -p ${INSTALL_SCRIPT_DIR} ;fi
|
||||
@if [ ! -d ${INSTALL_SERVICE_DIR} ]; then mkdir -p ${INSTALL_SERVICE_DIR} ;fi
|
||||
@if [ ! -d ${CTC_48GT4X_PHY_DIR} ]; then mkdir -p ${CTC_48GT4X_PHY_DIR}/phy_drv ;fi
|
||||
@if [ ! -d ${INSTALL_LIB_DIR} ]; then mkdir -p ${INSTALL_LIB_DIR} ;fi
|
||||
@if [ -d $(PWD)/lib/ ]; then cp -r $(PWD)/lib/* ${INSTALL_LIB_DIR} ;fi
|
||||
cp -r $(app_dir)/*.so $(CTC_48GT4X_PHY_DIR)/phy_drv
|
||||
cp -r $(app_build_dir)/module/*.ko $(INSTALL_MODULE_DIR)
|
||||
cp -r $(modules_build_dir)/*.ko $(INSTALL_MODULE_DIR)
|
||||
cp -r $(app_dir)/build/app/* $(INSTALL_SCRIPT_DIR)
|
||||
if [ -d $(SCRIPT_DIR) ]; then cp -r $(SCRIPT_DIR)/* $(INSTALL_SCRIPT_DIR) ;fi
|
||||
if [ -d $(SERVICE_DIR) ]; then cp -r $(SERVICE_DIR)/* $(INSTALL_SERVICE_DIR) ;fi
|
||||
@if [ -d $(INSTALL_SCRIPT_DIR) ]; then chmod +x $(INSTALL_SCRIPT_DIR)/* ;fi
|
||||
clean:
|
||||
rm -rf $(SUB_BUILD_DIR)
|
@ -1,26 +0,0 @@
|
||||
pes_parent_dir:=$(shell pwd)/$(lastword $(MAKEFILE_LIST))
|
||||
pes_parent_dir:=$(shell dirname $(pes_parent_dir))
|
||||
|
||||
SUBDIRS=$(shell ls -l | grep ^d | awk '{if($$9 != "build") print $$9}')
|
||||
INC = -I./inc
|
||||
|
||||
COMMON_OUT_PUT := $(shell pwd)/build
|
||||
common_out_put_dir := $(COMMON_OUT_PUT)/app
|
||||
common_module_dir := $(COMMON_OUT_PUT)/module/
|
||||
export common_out_put_dir common_module_dir
|
||||
|
||||
all : CHECK $(SUBDIRS)
|
||||
CHECK :
|
||||
@echo $(pes_parent_dir)
|
||||
|
||||
$(SUBDIRS):ECHO
|
||||
# make all
|
||||
#@echo $@
|
||||
make -C $@
|
||||
|
||||
ECHO:
|
||||
@echo $(SUBDIRS)
|
||||
|
||||
.PHONY : clean
|
||||
clean :
|
||||
-rm -rf $(COMMON_OUT_PUT)
|
@ -1,20 +0,0 @@
|
||||
top_srcdir:= $(shell pwd)
|
||||
include $(top_srcdir)/Rules.mk
|
||||
export top_srcdir
|
||||
|
||||
firmware-y:=
|
||||
firmware-y += firmware_driver_ispvme
|
||||
firmware-y += firmware_upgrade_ispvme
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
|
||||
.PHONY: build
|
||||
build: $(firmware-y)
|
||||
$(foreach dir,$(firmware-y),$(eval $(call compile_dirs,$(dir))))
|
||||
|
||||
.PHONY: rpmpkg
|
||||
rpmpkg:
|
||||
ifeq ("$(CONFIG_CPLD_UPGRADE_ISPVME)", "y")
|
||||
#$(RPMPKG) $(install_cpld_dir) firmware-cpld-ispvme.spec git
|
||||
endif
|
@ -1,45 +0,0 @@
|
||||
CC ?= $(CROSS)gcc
|
||||
AR ?= $(CROSS)ar
|
||||
AS ?= $(CROSS)as
|
||||
LD ?= $(CROSS)ld
|
||||
STRIP ?= $(CROSS)strip
|
||||
|
||||
install_root:=${top_srcdir}/images
|
||||
|
||||
install_header_dir:=${install_root}/header
|
||||
install_adir:=$(install_root)/lib
|
||||
install_symbol_dir:=$(install_root)/symbol
|
||||
# symbol_files
|
||||
symbol_files:=$(shell find $(EXPORT_SYMBOL) -name 'Module.symvers')
|
||||
#
|
||||
# symbol_files += $(shell find $(install_symbol_dir) -name 'Module.symvers')
|
||||
|
||||
# top root: install_rootfs_dir
|
||||
# install_rootfs_dir
|
||||
install_rootfs_dir:=$(install_root)/rootfs
|
||||
|
||||
# install_sodir
|
||||
install_sodir:=$(install_rootfs_dir)/$(INSTALL_SODIR)
|
||||
|
||||
install_usr_bin_dir:=$(install_rootfs_dir)/usr/bin
|
||||
# install_sbin_dir
|
||||
install_sbin_dir:=$(install_rootfs_dir)/sbin
|
||||
install_etc_dir:=$(install_rootfs_dir)/etc
|
||||
|
||||
export INSTALL_MOD_PATH:=$(ROOT)
|
||||
|
||||
BUILD_CFLAGS:=$(CFLAGS) -I$(install_header_dir)
|
||||
BUILD_LDFLAGS:=$(LDFLAGS) -L/$(install_sodir) -L/$(install_adir)
|
||||
|
||||
define compile_dirs
|
||||
.PHONY: $(1)
|
||||
$(1):
|
||||
@echo;echo "building $(1)..."
|
||||
@$(MAKE) -C ${1}
|
||||
endef
|
||||
|
||||
compile.c = $(CC) $(BUILD_CFLAGS) -d -c -o $@ $<
|
||||
|
||||
%.o: %.c
|
||||
$(compile.c)
|
||||
|
@ -1,25 +0,0 @@
|
||||
Summary: Firmware Upgrade Package
|
||||
|
||||
Name: firmware-cpld
|
||||
|
||||
Version: 1.0.0.%patch
|
||||
|
||||
Release: firmware
|
||||
|
||||
License: Ragile
|
||||
|
||||
Group: common
|
||||
|
||||
AutoReqProv: no
|
||||
|
||||
%clean
|
||||
%description
|
||||
[common]
|
||||
%des_name
|
||||
%des_ver
|
||||
%des_target
|
||||
|
||||
%files
|
||||
|
||||
%attr(755,root,root)
|
||||
/*
|
@ -1,22 +0,0 @@
|
||||
PWD = $(shell pwd)
|
||||
|
||||
EXTRA_CFLAGS:= -I$(M)/include
|
||||
EXTRA_CFLAGS+= -Wall
|
||||
ifdef ENABLE_GCOV
|
||||
ifeq ($(ENABLE_GCOV), y)
|
||||
EXTRA_CFLAGS+= -fprofile-arcs -ftest-coverage -lgcov
|
||||
endif
|
||||
endif # ENABLE_GCOV
|
||||
RAGILE_PRODUCT = ra_b6010_48gt4x
|
||||
firmware_driver-objs := firmware_ispvme.o
|
||||
firmware_driver-objs += firmware_cpld_ispvme.o firmware_cpld_upgrade_ispvme.o
|
||||
|
||||
#ifndef CONFIG_FRM_PRODUCT_FILE
|
||||
|
||||
firmware_driver-objs += $(RAGILE_PRODUCT).o
|
||||
$(warning $(firmware_driver-objs))
|
||||
obj-m := firmware_driver.o
|
||||
all:
|
||||
$(MAKE) -C $(KERNEL_SRC)/build M=$(PWD) modules
|
||||
@if [ ! -d $(common_module_dir) ]; then mkdir -p $(common_module_dir) ;fi
|
||||
cp -p $(PWD)/*.ko $(common_module_dir)
|
@ -1,283 +0,0 @@
|
||||
/**
|
||||
* Copyright(C) 2013 Ragile Network. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* firmware_cpld.c
|
||||
* Original Author : support <support@ragile.com> 2013-10-25
|
||||
*
|
||||
* CPLD driver
|
||||
*
|
||||
* History
|
||||
* v1.0 support <support@ragile.com> 2013-10-25 Initial version.
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/of.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <firmware_ispvme.h>
|
||||
#include <firmware_cpld_ispvme.h>
|
||||
|
||||
static int firmware_cpld_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
firmware_cpld_t *cpld_info;
|
||||
firmware_device_t *frm_dev;
|
||||
|
||||
dev_debug(firmware_debug(), "Open cpld device.\n");
|
||||
|
||||
frm_dev = firmware_get_device_by_minor(FIRMWARE_CPLD, MINOR(inode->i_rdev));
|
||||
if (frm_dev == NULL) {
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
file->private_data = frm_dev;
|
||||
cpld_info = (firmware_cpld_t *)frm_dev->priv;
|
||||
|
||||
if (cpld_info != NULL && cpld_info->init_cpld) {
|
||||
cpld_info->init_cpld();
|
||||
}
|
||||
|
||||
if (cpld_info != NULL && cpld_info->init_chip) {
|
||||
cpld_info->init_chip(0);
|
||||
}
|
||||
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
static ssize_t firmware_cpld_read (struct file *file, char __user *buf, size_t count,
|
||||
loff_t *offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t firmware_cpld_write (struct file *file, const char __user *buf, size_t count,
|
||||
loff_t *offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static loff_t firmware_cpld_llseek(struct file *file, loff_t offset, int origin)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long firmware_cpld_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
char value;
|
||||
void __user *argp;
|
||||
cmd_info_t cmd_info;
|
||||
char *buf;
|
||||
int ret;
|
||||
|
||||
argp = (void __user *)arg;
|
||||
|
||||
switch (cmd) {
|
||||
case FIRMWARE_JTAG_TDI:
|
||||
if (copy_from_user(&value, argp, sizeof(value))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
fwm_cpld_tdi_op(value);
|
||||
break;
|
||||
case FIRMWARE_JTAG_TCK:
|
||||
if (copy_from_user(&value, argp, sizeof(value))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
fwm_cpld_tck_op(value);
|
||||
break;
|
||||
|
||||
case FIRMWARE_JTAG_TMS:
|
||||
if (copy_from_user(&value, argp, sizeof(value))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
fwm_cpld_tms_op(value);
|
||||
break;
|
||||
|
||||
case FIRMWARE_JTAG_TDO:
|
||||
value = fwm_cpld_tdo_op();
|
||||
|
||||
if (copy_to_user(argp, &value, sizeof(value))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FIRMWARE_SET_GPIO_INFO:
|
||||
/* set GPIO information */
|
||||
if (copy_from_user(&cmd_info, argp, sizeof(cmd_info_t))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
buf = (char *) kzalloc(cmd_info.size + 1, GFP_KERNEL);
|
||||
if (buf == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (copy_from_user(buf, cmd_info.data, cmd_info.size)) {
|
||||
kfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = fmw_cpld_set_gpio_info((firmware_upg_gpio_info_t*)buf);
|
||||
if (ret != FIRMWARE_SUCCESS) {
|
||||
dev_debug(firmware_debug(), "Failed to set gpio info.\n");
|
||||
kfree(buf);
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
break;
|
||||
|
||||
case FIRMWARE_SET_DEBUG_ON:
|
||||
/* DEBUG ON */
|
||||
firmware_set_debug(1);
|
||||
break;
|
||||
case FIRMWARE_SET_DEBUG_OFF:
|
||||
/* DEBUG_OFF */
|
||||
firmware_set_debug(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
static int firmware_cpld_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
firmware_cpld_t *cpld_info;
|
||||
firmware_device_t *frm_dev;
|
||||
|
||||
frm_dev = (firmware_device_t *)(file->private_data);
|
||||
cpld_info = (firmware_cpld_t *)(frm_dev->priv);
|
||||
|
||||
if (cpld_info != NULL && cpld_info->finish_chip) {
|
||||
cpld_info->finish_chip(0);
|
||||
}
|
||||
|
||||
if (cpld_info != NULL && cpld_info->finish_cpld) {
|
||||
cpld_info->finish_cpld();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations cpld_dev_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = firmware_cpld_llseek,
|
||||
.read = firmware_cpld_read,
|
||||
.write = firmware_cpld_write,
|
||||
.unlocked_ioctl = firmware_cpld_ioctl,
|
||||
.open = firmware_cpld_open,
|
||||
.release = firmware_cpld_release,
|
||||
};
|
||||
|
||||
static int firmware_cpld_probe(struct platform_device *pdev)
|
||||
{
|
||||
const __be32 *slot;
|
||||
int len;
|
||||
int ret;
|
||||
firmware_cpld_t *cpld_info;
|
||||
firmware_device_t *frm_dev;
|
||||
|
||||
frm_dev = (firmware_device_t *) kzalloc(sizeof(firmware_device_t), GFP_KERNEL);
|
||||
if (frm_dev == NULL) {
|
||||
dev_debug(firmware_debug(), "Failed to kzalloc firmware device.\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
slot = of_get_property(pdev->dev.of_node, "slot", &len);
|
||||
if (slot && len == sizeof(*slot)) {
|
||||
frm_dev->slot = be32_to_cpup(slot);
|
||||
} else {
|
||||
frm_dev->slot = firmware_get_device_num(FIRMWARE_CPLD) + 1;
|
||||
}
|
||||
|
||||
snprintf(frm_dev->name, FIRMWARE_NAME_LEN - 1, "firmware_cpld_ispvme%d", frm_dev->slot - 1);
|
||||
cpld_info = fmw_cpld_upg_get_cpld(frm_dev->name);
|
||||
|
||||
INIT_LIST_HEAD(&frm_dev->list);
|
||||
frm_dev->type = FIRMWARE_CPLD;
|
||||
frm_dev->dev.minor = MISC_DYNAMIC_MINOR;
|
||||
frm_dev->dev.name = frm_dev->name;
|
||||
frm_dev->dev.fops = &cpld_dev_fops;
|
||||
frm_dev->priv = cpld_info;
|
||||
|
||||
dev_debug(firmware_debug(), "Register cpld firmware slot:%d, name:%s.\n", frm_dev->slot, frm_dev->name);
|
||||
|
||||
ret = firmware_device_register(frm_dev);
|
||||
if (ret < 0) {
|
||||
dev_debug(firmware_debug(), "Failed to register firmware device.\n");
|
||||
kfree(frm_dev);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, frm_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __exit firmware_cpld_remove(struct platform_device *dev)
|
||||
{
|
||||
firmware_device_t *frm_dev;
|
||||
|
||||
frm_dev = (firmware_device_t *)platform_get_drvdata(dev);
|
||||
firmware_device_unregister(frm_dev);
|
||||
|
||||
kfree(frm_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id cpld_match[] = {
|
||||
{
|
||||
.compatible = "firmware_cpld_ispvme",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver cpld_driver = {
|
||||
.driver = {
|
||||
.name = "firmware_cpld_ispvme",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = cpld_match,
|
||||
},
|
||||
.probe = firmware_cpld_probe,
|
||||
.remove = firmware_cpld_remove,
|
||||
};
|
||||
|
||||
static firmware_driver_t fmw_drv = {
|
||||
.name = "firmware_cpld_ispvme",
|
||||
.type = FIRMWARE_CPLD,
|
||||
.drv = &cpld_driver,
|
||||
};
|
||||
|
||||
void firmware_cpld_init(void)
|
||||
{
|
||||
int ret;
|
||||
#if 0
|
||||
struct device_node* node;
|
||||
node = of_find_node_by_name(NULL, "cpld_upgrade");
|
||||
if (node == NULL) {
|
||||
pr_notice("No cpld_upgrade\r\n");
|
||||
return;
|
||||
}
|
||||
pr_notice("Found cpld_upgrade\r\n");
|
||||
#else
|
||||
printk(KERN_INFO "Do init cpld_upgrade\r\n");
|
||||
#endif
|
||||
INIT_LIST_HEAD(&fmw_drv.list);
|
||||
ret = fmw_cpld_upg_init();
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
firmware_driver_register(&fmw_drv);
|
||||
}
|
||||
|
||||
void firmware_cpld_exit(void)
|
||||
{
|
||||
fmw_cpld_upg_exit();
|
||||
firmware_driver_unregister(&fmw_drv);
|
||||
INIT_LIST_HEAD(&fmw_drv.list);
|
||||
}
|
@ -1,329 +0,0 @@
|
||||
/**
|
||||
* Copyright(C) 2013 Ragile Network. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* firmware_cpld_upgrade.c
|
||||
* Original Author : support <support@ragile.com>2013-10-25
|
||||
*
|
||||
* CPLD upgrade driver
|
||||
*
|
||||
* History
|
||||
* v1.0 support <support@ragile.com> 2013-10-25 Initial version.
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <firmware_ispvme.h>
|
||||
#include <firmware_cpld_ispvme.h>
|
||||
#include <config_ispvme.h>
|
||||
|
||||
/* TCK clock MAX 16MHz */
|
||||
#define TCK_DELAY (current_fmw_cpld->tck_delay)
|
||||
#if 0
|
||||
static firmware_cpld_t default_fmw_cpld;
|
||||
#endif
|
||||
static firmware_cpld_t fmw_cpld[FIRMWARE_MAX_CPLD_NUM];
|
||||
static firmware_cpld_t *current_fmw_cpld;
|
||||
|
||||
static firmware_set_gpio_info_func_t g_set_gpio_info_func = NULL;
|
||||
|
||||
void set_currrent_cpld_info(firmware_cpld_t *info)
|
||||
{
|
||||
current_fmw_cpld = info;
|
||||
}
|
||||
|
||||
static void TDI_PULL_DOWN(void)
|
||||
{
|
||||
if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tdi_down) {
|
||||
current_fmw_cpld->pull_tdi_down();
|
||||
} else {
|
||||
dev_debug(firmware_debug(), "NO support TDI_PULL_DOWN.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void TDI_PULL_UP(void)
|
||||
{
|
||||
if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tdi_up) {
|
||||
current_fmw_cpld->pull_tdi_up();
|
||||
} else {
|
||||
dev_debug(firmware_debug(), "NO support TDI_PULL_UP.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void TCK_PULL_DOWN(void)
|
||||
{
|
||||
if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tck_down) {
|
||||
current_fmw_cpld->pull_tck_down();
|
||||
} else {
|
||||
dev_debug(firmware_debug(), "NO support TCK_PULL_DOWN.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void TCK_PULL_UP(void)
|
||||
{
|
||||
if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tck_up) {
|
||||
current_fmw_cpld->pull_tck_up();
|
||||
} else {
|
||||
dev_debug(firmware_debug(), "NO support TCK_PULL_UP.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void TMS_PULL_DOWN(void)
|
||||
{
|
||||
if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tms_down) {
|
||||
current_fmw_cpld->pull_tms_down();
|
||||
} else {
|
||||
dev_debug(firmware_debug(), "NO support TMS_PULL_DOWN.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void TMS_PULL_UP(void)
|
||||
{
|
||||
if (current_fmw_cpld != NULL && current_fmw_cpld->pull_tms_up) {
|
||||
current_fmw_cpld->pull_tms_up();
|
||||
} else {
|
||||
dev_debug(firmware_debug(), "NO support TMS_PULL_UP.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int TDO_READ(void)
|
||||
{
|
||||
if (current_fmw_cpld != NULL && current_fmw_cpld->read_tdo) {
|
||||
return current_fmw_cpld->read_tdo();
|
||||
} else {
|
||||
dev_debug(firmware_debug(), "NO support TDO_READ.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
firmware_cpld_t *fmw_cpld_upg_get_cpld(char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FIRMWARE_MAX_CPLD_NUM; i++) {
|
||||
if (fmw_cpld[i].is_used == 1 && strcmp(name, fmw_cpld[i].devname) == 0) {
|
||||
return &fmw_cpld[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fmw_cpld_upg_copy_firmware_info(firmware_cpld_t *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FIRMWARE_MAX_CPLD_NUM; i++) {
|
||||
if (fmw_cpld[i].is_used == 1) {
|
||||
continue;
|
||||
} else {
|
||||
strncpy(fmw_cpld[i].devname, info->devname, FIRMWARE_DEV_NAME_LEN);
|
||||
fmw_cpld[i].slot = info->slot;
|
||||
fmw_cpld[i].chip_index = info->chip_index;
|
||||
fmw_cpld[i].is_used = info->is_used;
|
||||
fmw_cpld[i].tck_delay = info->tck_delay;
|
||||
fmw_cpld[i].pull_tdi_up = info->pull_tdi_up;
|
||||
fmw_cpld[i].pull_tdi_down = info->pull_tdi_down;
|
||||
fmw_cpld[i].pull_tck_up = info->pull_tck_up;
|
||||
fmw_cpld[i].pull_tck_down = info->pull_tck_down;
|
||||
fmw_cpld[i].pull_tms_up = info->pull_tms_up;
|
||||
fmw_cpld[i].pull_tms_down = info->pull_tms_down;
|
||||
fmw_cpld[i].read_tdo = info->read_tdo;
|
||||
fmw_cpld[i].init_cpld = info->init_cpld;
|
||||
fmw_cpld[i].init_chip = info->init_chip;
|
||||
fmw_cpld[i].finish_chip = info->finish_chip;
|
||||
fmw_cpld[i].finish_cpld = info->finish_cpld;
|
||||
fmw_cpld[i].touch_watch_dog = info->touch_watch_dog;
|
||||
fmw_cpld[i].keeplive = info->keeplive;
|
||||
fmw_cpld[i].get_version = info->get_version;
|
||||
fmw_cpld[i].get_card_name = info->get_card_name;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fmw_cpld_set_gpio_info(firmware_upg_gpio_info_t *info)
|
||||
{
|
||||
if (g_set_gpio_info_func == NULL) {
|
||||
dev_debug(firmware_debug(), "g_set_gpio_info_func is null.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return g_set_gpio_info_func(info);
|
||||
}
|
||||
|
||||
void fmw_cpld_reg_gpio_info_set_func(firmware_set_gpio_info_func_t func)
|
||||
{
|
||||
if (func == NULL) {
|
||||
dev_debug(firmware_debug(), "fmw_cpld_register_gpio_info_set_func func = NULL.\n");
|
||||
return;
|
||||
}
|
||||
g_set_gpio_info_func = func;
|
||||
return;
|
||||
|
||||
}
|
||||
#if 0
|
||||
/* CPLD upgrade initialization operation */
|
||||
static int fmw_cpld_upg_init_cpld(void)
|
||||
{
|
||||
gpio_request(JTAG_TDI, "cpld_upgrade");
|
||||
gpio_request(JTAG_TCK, "cpld_upgrade");
|
||||
gpio_request(JTAG_TMS, "cpld_upgrade");
|
||||
gpio_request(JTAG_EN, "cpld_upgrade");
|
||||
gpio_request(JTAG_TDO, "cpld_upgrade");
|
||||
|
||||
gpio_direction_output(JTAG_TDI, 1);
|
||||
gpio_direction_output(JTAG_TCK, 1);
|
||||
gpio_direction_output(JTAG_TMS, 1);
|
||||
gpio_direction_output(JTAG_EN, 1);
|
||||
|
||||
gpio_direction_input(JTAG_TDO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CPLD upgrade completion operation */
|
||||
static int fmw_cpld_upg_finish_cpld(void)
|
||||
{
|
||||
gpio_direction_output(JTAG_EN, 0);
|
||||
|
||||
gpio_free(JTAG_TDI);
|
||||
gpio_free(JTAG_TCK);
|
||||
gpio_free(JTAG_TMS);
|
||||
gpio_free(JTAG_EN);
|
||||
gpio_free(JTAG_TDO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TDI pull up */
|
||||
static void fmw_cpld_upg_pull_tdi_up(void)
|
||||
{
|
||||
__gpio_set_value(JTAG_TDI, 1);
|
||||
}
|
||||
|
||||
/* TDI pull down */
|
||||
static void fmw_cpld_upg_pull_tdi_down(void)
|
||||
{
|
||||
__gpio_set_value(JTAG_TDI, 0);
|
||||
}
|
||||
|
||||
/* TCK pull up */
|
||||
static void fmw_cpld_upg_pull_tck_up(void)
|
||||
{
|
||||
__gpio_set_value(JTAG_TCK, 1);
|
||||
}
|
||||
|
||||
/* TCK pull down */
|
||||
static void fmw_cpld_upg_pull_tck_down(void)
|
||||
{
|
||||
__gpio_set_value(JTAG_TCK, 0);
|
||||
}
|
||||
|
||||
/* TMS pull up */
|
||||
static void fmw_cpld_upg_pull_tms_up(void)
|
||||
{
|
||||
__gpio_set_value(JTAG_TMS, 1);
|
||||
}
|
||||
|
||||
/* TCK pull down */
|
||||
static void fmw_cpld_upg_pull_tms_down(void)
|
||||
{
|
||||
__gpio_set_value(JTAG_TMS, 0);
|
||||
}
|
||||
|
||||
/* read TDO */
|
||||
static int fmw_cpld_upg_read_tdo(void)
|
||||
{
|
||||
return __gpio_get_value(JTAG_TDO);
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
static firmware_cpld_t default_fmw_cpld = {
|
||||
.devname = "default_firmware_cpld",
|
||||
.slot = 1,
|
||||
.is_used = 1,
|
||||
.tck_delay = 50,
|
||||
.pull_tdi_up = fmw_cpld_upg_pull_tdi_up,
|
||||
.pull_tdi_down = fmw_cpld_upg_pull_tdi_down,
|
||||
.pull_tck_up = fmw_cpld_upg_pull_tck_up,
|
||||
.pull_tck_down = fmw_cpld_upg_pull_tck_down,
|
||||
.pull_tms_up = fmw_cpld_upg_pull_tms_up,
|
||||
.pull_tms_down = fmw_cpld_upg_pull_tms_down,
|
||||
.read_tdo = fmw_cpld_upg_read_tdo,
|
||||
.init_cpld = fmw_cpld_upg_init_cpld,
|
||||
.finish_cpld = fmw_cpld_upg_finish_cpld,
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Each product initializes its own related CPLD driver and needs to re-define the interface
|
||||
* In the new interface, assign the relevant driver to fmw_cpld through the fmw_cpld_upg_copy_firmware_info interface
|
||||
*/
|
||||
int __attribute__ ((weak))fmw_cpld_product_init(void)
|
||||
{
|
||||
dev_debug(firmware_debug(), "Nothing cpld init for this product.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __attribute__ ((weak))fmw_cpld_product_exit(void)
|
||||
{
|
||||
dev_debug(firmware_debug(), "Nothing exit init for this product.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int fmw_cpld_upg_init(void)
|
||||
{
|
||||
int ret;
|
||||
mem_clear(fmw_cpld, FIRMWARE_MAX_CPLD_NUM * sizeof(firmware_cpld_t));
|
||||
ret = fmw_cpld_product_init();
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
#if 0
|
||||
set_currrent_cpld_info(&default_fmw_cpld);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fmw_cpld_upg_exit(void)
|
||||
{
|
||||
fmw_cpld_product_exit();
|
||||
return;
|
||||
}
|
||||
|
||||
void fwm_cpld_tdi_op(int value)
|
||||
{
|
||||
if (value) {
|
||||
TDI_PULL_UP();
|
||||
} else {
|
||||
TDI_PULL_DOWN();
|
||||
}
|
||||
}
|
||||
|
||||
void fwm_cpld_tck_op(int value)
|
||||
{
|
||||
if (value) {
|
||||
TCK_PULL_UP();
|
||||
} else {
|
||||
TCK_PULL_DOWN();
|
||||
}
|
||||
}
|
||||
|
||||
void fwm_cpld_tms_op(int value)
|
||||
{
|
||||
if (value) {
|
||||
TMS_PULL_UP();
|
||||
} else {
|
||||
TMS_PULL_DOWN();
|
||||
}
|
||||
}
|
||||
|
||||
int fwm_cpld_tdo_op()
|
||||
{
|
||||
return TDO_READ();
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
/**
|
||||
* Copyright(C) 2013 Ragile Network. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* firmware.c
|
||||
* Original Author : support <support@ragile.com>2013-10-25
|
||||
*
|
||||
* firmware upgrade driver
|
||||
*
|
||||
* History
|
||||
* v1.0 support <support@ragile.com> 2013-10-25 Initial version.
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <firmware_ispvme.h>
|
||||
#include <config_ispvme.h>
|
||||
|
||||
int drv_debug = 0;
|
||||
module_param(drv_debug, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
static LIST_HEAD(drv_list);
|
||||
static LIST_HEAD(dev_list);
|
||||
|
||||
void firmware_set_debug(int value)
|
||||
{
|
||||
drv_debug = value;
|
||||
return;
|
||||
}
|
||||
|
||||
int firmware_debug(void)
|
||||
{
|
||||
return drv_debug;
|
||||
}
|
||||
|
||||
int firmware_driver_register(firmware_driver_t *fw_drv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (fw_drv == NULL) {
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(fw_drv->drv);
|
||||
if (ret < 0) {
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
list_add(&fw_drv->list, &drv_list);
|
||||
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
void firmware_driver_unregister(firmware_driver_t *fw_drv)
|
||||
{
|
||||
list_del_init(&fw_drv->list);
|
||||
platform_driver_unregister(fw_drv->drv);
|
||||
}
|
||||
|
||||
int firmware_get_device_num(int type)
|
||||
{
|
||||
int num;
|
||||
firmware_device_t *tmp;
|
||||
|
||||
num = 0;
|
||||
list_for_each_entry(tmp, &dev_list, list) {
|
||||
if (tmp->type == type) {
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
firmware_device_t *firmware_get_device_by_minor(int type, int minor)
|
||||
{
|
||||
firmware_device_t *tmp;
|
||||
|
||||
list_for_each_entry(tmp, &dev_list, list) {
|
||||
if (tmp->type == type && tmp->dev.minor == minor) {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int firmware_device_register(firmware_device_t *fw_dev)
|
||||
{
|
||||
int ret;
|
||||
firmware_device_t *tmp;
|
||||
|
||||
if (fw_dev == NULL) {
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
list_for_each_entry(tmp, &dev_list, list) {
|
||||
if (strcmp(tmp->name, fw_dev->name) == 0) {
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ret = misc_register(&fw_dev->dev);
|
||||
if (ret < 0) {
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
list_add(&fw_dev->list, &dev_list);
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
void firmware_device_unregister(firmware_device_t *fw_dev)
|
||||
{
|
||||
list_del(&fw_dev->list);
|
||||
misc_deregister(&fw_dev->dev);
|
||||
}
|
||||
|
||||
static int __init firmware_driver_init(void)
|
||||
{
|
||||
INIT_LIST_HEAD(&drv_list);
|
||||
INIT_LIST_HEAD(&dev_list);
|
||||
dev_debug(firmware_debug(), "firmware_driver_init cpld init.\n");
|
||||
firmware_cpld_init();
|
||||
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
static void __exit firmware_driver_exit(void)
|
||||
{
|
||||
dev_debug(firmware_debug(), "firmware_driver_exit cpld exit.\n");
|
||||
firmware_cpld_exit();
|
||||
INIT_LIST_HEAD(&drv_list);
|
||||
INIT_LIST_HEAD(&dev_list);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(firmware_driver_init);
|
||||
module_exit(firmware_driver_exit);
|
||||
|
||||
MODULE_AUTHOR("support <support@ragile.com>");
|
||||
MODULE_DESCRIPTION("ragile Platform Support");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,10 +0,0 @@
|
||||
#ifndef __CONFIG_H__
|
||||
#define __CONFIG_H__
|
||||
|
||||
#define JTAG_TDI (32)
|
||||
#define JTAG_TDO (67)
|
||||
#define JTAG_TCK (65)
|
||||
#define JTAG_TMS (6)
|
||||
#define JTAG_EN (50)
|
||||
|
||||
#endif /* __CONFIG_H__ */
|
@ -1,52 +0,0 @@
|
||||
#ifndef __FIRMWARE_CPLD_H__
|
||||
#define __FIRMWARE_CPLD_H__
|
||||
|
||||
#define FIRMWARE_DEV_NAME_LEN 32
|
||||
#define FIRMWARE_MAX_CPLD_NUM 16
|
||||
|
||||
typedef struct firmware_cpld_s {
|
||||
char devname[FIRMWARE_DEV_NAME_LEN];
|
||||
int slot;
|
||||
int chip_index;
|
||||
int is_used; /* 0:unused 1:used */
|
||||
u32 tck_delay; /* delay time */
|
||||
void (*pull_tdi_up)(void); /* TDI pull up */
|
||||
void (*pull_tdi_down)(void); /* TDI pull dowm */
|
||||
void (*pull_tck_up)(void); /* TCK pull up */
|
||||
void (*pull_tck_down)(void); /* TCK pull dowm */
|
||||
void (*pull_tms_up)(void); /* TMS pull up */
|
||||
void (*pull_tms_down)(void); /* TCK pull dowm */
|
||||
int (*read_tdo)(void); /* read ?TDO */
|
||||
int (*init_cpld)(void); /* CPLD upgrade initialization operation */
|
||||
int (*init_chip)(int slot); /* Chip related initialization operations */
|
||||
int (*finish_chip)(int slot); /* Chip related completion operations */
|
||||
int (*finish_cpld)(void); /* CPLD upgrade completion operation */
|
||||
int (*check_upgrade_data)(char *src, int src_len, int *dst, int dst_len);
|
||||
int (*touch_watch_dog)(void); /* touch watch dog related operation */
|
||||
int (*keeplive)(void); /* KEEPLIVE */
|
||||
int (*get_version)(int slot, char *ver, int len);
|
||||
int (*get_card_name)(char *name, int len); /* get card name */
|
||||
} firmware_cpld_t;
|
||||
|
||||
typedef int (*firmware_set_gpio_info_func_t)(firmware_upg_gpio_info_t *info);
|
||||
|
||||
extern int fmw_cpld_upg_get_chip_name(int slot, firmware_cpld_t *cpld, char *info, int len);
|
||||
extern int fmw_cpld_upg_get_card_name(int slot, firmware_cpld_t *cpld, char *info, int len);
|
||||
extern int fmw_cpld_upg_program(int slot, firmware_cpld_t *cpld, char *info, int len);
|
||||
extern int fmw_cpld_upg_get_version(int slot, firmware_cpld_t *cpld, char *info, int len);
|
||||
extern firmware_cpld_t *fmw_cpld_upg_get_cpld(char *name);
|
||||
extern int fmw_cpld_upg_init(void);
|
||||
extern void fmw_cpld_upg_exit(void);
|
||||
extern int fmw_cpld_upg_copy_firmware_info(firmware_cpld_t *info);
|
||||
extern int fmw_cpld_upg_get_chip_info(int slot, firmware_cpld_t *cpld, void *info, int len);
|
||||
|
||||
extern void fwm_cpld_tdi_op(int value);
|
||||
extern void fwm_cpld_tck_op(int value);
|
||||
extern void fwm_cpld_tms_op(int value);
|
||||
extern int fwm_cpld_tdo_op(void);
|
||||
extern void firmware_cpld_upgrade_init(void);
|
||||
extern void firmware_cpld_upgrade_finish(void);
|
||||
extern int fmw_cpld_set_gpio_info(firmware_upg_gpio_info_t *info);
|
||||
extern void fmw_cpld_reg_gpio_info_set_func(firmware_set_gpio_info_func_t func);
|
||||
|
||||
#endif /* __FIRMWARE_CPLD_H__ */
|
@ -1,90 +0,0 @@
|
||||
#ifndef __FIRMWARE_H__
|
||||
#define __FIRMWARE_H__
|
||||
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/ioctl.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#define mem_clear(data, size) memset((data), 0, (size))
|
||||
#define dev_debug(debug, fmt, arg...) \
|
||||
if (debug == 1) { do{printk(KERN_ERR fmt,##arg);} while(0); }
|
||||
|
||||
#define FIRMWARE_NAME_LEN 48
|
||||
|
||||
#define FIRMWARE_FAILED (-1)
|
||||
#define FIRMWARE_SUCCESS 0
|
||||
|
||||
enum firmware_type_s {
|
||||
FIRMWARE_CPLD = 0,
|
||||
FIRMWARE_FPGA,
|
||||
};
|
||||
|
||||
/* ioctl command */
|
||||
#define FIRMWARE_TYPE 'F'
|
||||
#define FIRMWARE_JTAG_TDI _IOR(FIRMWARE_TYPE, 0, char)
|
||||
#define FIRMWARE_JTAG_TDO _IOR(FIRMWARE_TYPE, 1, char)
|
||||
#define FIRMWARE_JTAG_TCK _IOR(FIRMWARE_TYPE, 2, char)
|
||||
#define FIRMWARE_JTAG_TMS _IOR(FIRMWARE_TYPE, 3, char)
|
||||
#define FIRMWARE_JTAG_EN _IOR(FIRMWARE_TYPE, 4, char)
|
||||
#define FIRMWARE_SET_DEBUG_ON _IOW(FIRMWARE_TYPE, 5, int) /* debug on */
|
||||
#define FIRMWARE_SET_DEBUG_OFF _IOW(FIRMWARE_TYPE, 6, int) /* debug off */
|
||||
#define FIRMWARE_SET_GPIO_INFO _IOR(FIRMWARE_TYPE, 7, int) /* Set GPIO pin configuration */
|
||||
|
||||
typedef struct cmd_info_s {
|
||||
int size;
|
||||
void __user *data;
|
||||
} cmd_info_t;
|
||||
|
||||
typedef struct firmware_device_s {
|
||||
struct list_head list; /* device linked list */
|
||||
int type; /* the type of device */
|
||||
int slot; /* position */
|
||||
char name[FIRMWARE_NAME_LEN]; /* name */
|
||||
struct miscdevice dev; /* device */
|
||||
void *priv; /* private data */
|
||||
} firmware_device_t;
|
||||
|
||||
typedef struct firmware_driver_s {
|
||||
struct list_head list; /* linked list */
|
||||
int type; /* type */
|
||||
char name[FIRMWARE_NAME_LEN]; /* name */
|
||||
struct platform_driver *drv; /* driver */
|
||||
void *priv; /* private data */
|
||||
} firmware_driver_t;
|
||||
|
||||
typedef struct gpio_group_s {
|
||||
int pin;
|
||||
int val;
|
||||
int dir;
|
||||
} gpio_group_t;
|
||||
|
||||
typedef struct firmware_upg_gpio_info_s {
|
||||
int tdi;
|
||||
int tck;
|
||||
int tms;
|
||||
int tdo;
|
||||
int jtag_en;
|
||||
int select;
|
||||
gpio_group_t jtag_5;
|
||||
gpio_group_t jtag_4;
|
||||
gpio_group_t jtag_3;
|
||||
gpio_group_t jtag_2;
|
||||
gpio_group_t jtag_1;
|
||||
} firmware_upg_gpio_info_t;
|
||||
|
||||
extern int firmware_debug(void);
|
||||
extern void firmware_set_debug(int value);
|
||||
extern firmware_device_t *firmware_get_device_by_minor(int type, int minor);
|
||||
extern int firmware_get_device_num(int type);
|
||||
extern int firmware_device_register(firmware_device_t *fw_dev);
|
||||
extern void firmware_device_unregister(firmware_device_t *fw_dev);
|
||||
extern int firmware_driver_register(firmware_driver_t *fw_drv);
|
||||
extern void firmware_driver_unregister(firmware_driver_t *fw_drv);
|
||||
extern void firmware_fpga_init(void);
|
||||
extern void firmware_cpld_init(void);
|
||||
extern void firmware_fpga_exit(void);
|
||||
extern void firmware_cpld_exit(void);
|
||||
|
||||
#endif /* end of __FIRMWARE_H__ */
|
@ -1,493 +0,0 @@
|
||||
/**
|
||||
* Copyright(C) 2013 Ragile Network. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* ca-octeon-cmx.c
|
||||
* Original Author : support <support@ragile.com>2013-10-25
|
||||
* ca-octeon-cmx CPLD upgrade driver
|
||||
*
|
||||
* firmware upgrade driver
|
||||
*
|
||||
* History
|
||||
* v1.0 support <support@ragile.com> 2013-10-25 Initial version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/gpio.h>
|
||||
#if 0
|
||||
#include <rg_switch_dev.h>
|
||||
#include <ssa/kernel_module/ssa_dfd_intf.h>
|
||||
#endif
|
||||
#include <firmware_ispvme.h>
|
||||
#include <firmware_cpld_ispvme.h>
|
||||
#include "ra_b6010_48gt4x.h"
|
||||
|
||||
/* extern void cmic_gpio_set_output_value(int gpio, int val); */
|
||||
firmware_device_info_t *current_info = NULL;
|
||||
static firmware_device_info_t set_gpio_info;
|
||||
static int set_gpio_info_flag = 0;
|
||||
firmware_device_info_t default_cpld_info = {
|
||||
.type = 0,
|
||||
.tdi = JTAG_TDI,
|
||||
.tck = JTAG_TCK,
|
||||
.tms = JTAG_TMS,
|
||||
.tdo = JTAG_TDO,
|
||||
.jtag_en = JTAG_EN,
|
||||
.select = -1,
|
||||
.cmic_start_gpio = -1,
|
||||
.cmic_end_gpio = -1,
|
||||
};
|
||||
|
||||
firmware_device_info_t as13_cpld_info = {
|
||||
.type = 0,
|
||||
.tdi = 67,
|
||||
.tck = JTAG_TCK,
|
||||
.tms = JTAG_TMS,
|
||||
.tdo = 32,
|
||||
.jtag_en = JTAG_EN,
|
||||
.select = 48,
|
||||
.cmic_start_gpio = -1,
|
||||
.cmic_end_gpio = -1,
|
||||
};
|
||||
|
||||
static int firmware_cpld_gpio_is_from_cmic(int gpio)
|
||||
{
|
||||
if (current_info == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev_debug(firmware_debug(), "gpio %d current_info.cmic_start_gpio %d current_info.cmic_end_gpio %d.\n",
|
||||
gpio, current_info->cmic_start_gpio, current_info->cmic_end_gpio);
|
||||
|
||||
if ((current_info->cmic_start_gpio == -1) || (current_info->cmic_end_gpio == -1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((gpio >= current_info->cmic_start_gpio) && (gpio <= current_info->cmic_end_gpio)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int firmware_cpld_gpio_get_value(int gpio)
|
||||
{
|
||||
#if 0
|
||||
int ret;
|
||||
|
||||
ret = firmware_cpld_gpio_is_from_cmic(gpio);
|
||||
if (ret < 0) {
|
||||
dev_debug(firmware_debug(), "firmware_cpld_gpio_is_from_cmic gpio %d failed ret %d.\n",
|
||||
gpio, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
/* Not currently supported */
|
||||
dev_debug(firmware_debug(), "gpio %d not support to get value.\n", gpio);
|
||||
return -1;
|
||||
} else {
|
||||
return __gpio_get_value(gpio);
|
||||
}
|
||||
#endif
|
||||
|
||||
return __gpio_get_value(gpio);
|
||||
}
|
||||
|
||||
static void firmware_cpld_gpio_set_output_value(int gpio, int val)
|
||||
{
|
||||
#if 0
|
||||
int ret;
|
||||
|
||||
ret = firmware_cpld_gpio_is_from_cmic(gpio);
|
||||
if (ret < 0) {
|
||||
dev_debug(firmware_debug(), "firmware_cpld_gpio_is_from_cmic gpio %d failed ret %d.\n",
|
||||
gpio, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
__gpio_set_value(gpio, val);
|
||||
/*cmic_gpio_set_output_value(gpio, val);*/
|
||||
} else {
|
||||
__gpio_set_value(gpio, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
__gpio_set_value(gpio, val);
|
||||
}
|
||||
|
||||
static void firmware_cpld_gpio_set_direction(int gpio, int out)
|
||||
{
|
||||
if (out) {
|
||||
gpio_direction_output(gpio, 1);
|
||||
} else {
|
||||
gpio_direction_input(gpio);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void firmware_cpld_gpio_request(int gpio, char *name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = firmware_cpld_gpio_is_from_cmic(gpio);
|
||||
if (ret < 0) {
|
||||
dev_debug(firmware_debug(), "firmware_cpld_gpio_is_from_cmic gpio %d failed ret %d.\n",
|
||||
gpio, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
/* do nothing */
|
||||
} else {
|
||||
gpio_request(gpio, name);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void firmware_cpld_gpio_free(int gpio)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = firmware_cpld_gpio_is_from_cmic(gpio);
|
||||
if (ret < 0) {
|
||||
dev_debug(firmware_debug(), "firmware_cpld_gpio_is_from_cmic gpio %d failed ret %d.\n",
|
||||
gpio, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
/* do nothing */
|
||||
} else {
|
||||
gpio_free(gpio);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* CPLD upgrade initialization operation */
|
||||
static int init_cpld(void)
|
||||
{
|
||||
if (current_info == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
firmware_cpld_gpio_request(current_info->tdi, "cpld_upgrade");
|
||||
firmware_cpld_gpio_request(current_info->tck, "cpld_upgrade");
|
||||
firmware_cpld_gpio_request(current_info->tms, "cpld_upgrade");
|
||||
firmware_cpld_gpio_request(current_info->jtag_en, "cpld_upgrade");
|
||||
if (current_info->select >= 0) {
|
||||
firmware_cpld_gpio_request(current_info->select, "cpld_upgrade");
|
||||
}
|
||||
firmware_cpld_gpio_request(current_info->tdo, "cpld_upgrade");
|
||||
if (current_info->jtag_4.pin >= 0){
|
||||
firmware_cpld_gpio_request(current_info->jtag_1.pin, "cpld_upgrade");
|
||||
firmware_cpld_gpio_request(current_info->jtag_2.pin, "cpld_upgrade");
|
||||
firmware_cpld_gpio_request(current_info->jtag_3.pin, "cpld_upgrade");
|
||||
firmware_cpld_gpio_request(current_info->jtag_4.pin, "cpld_upgrade");
|
||||
firmware_cpld_gpio_request(current_info->jtag_5.pin, "cpld_upgrade");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CPLD upgrade completion operation */
|
||||
static int finish_cpld(void)
|
||||
{
|
||||
if (current_info == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
firmware_cpld_gpio_set_output_value(current_info->jtag_en, 0);
|
||||
if (current_info->select >= 0) {
|
||||
firmware_cpld_gpio_set_output_value(current_info->select, 0);
|
||||
}
|
||||
if (current_info->jtag_4.pin >= 0) {
|
||||
gpio_direction_input(current_info->jtag_4.pin);
|
||||
gpio_direction_input(current_info->jtag_1.pin);
|
||||
gpio_direction_input(current_info->jtag_2.pin);
|
||||
gpio_direction_input(current_info->jtag_3.pin);
|
||||
gpio_direction_input(current_info->jtag_5.pin);
|
||||
}
|
||||
firmware_cpld_gpio_free(current_info->tdi);
|
||||
firmware_cpld_gpio_free(current_info->tck);
|
||||
firmware_cpld_gpio_free(current_info->tms);
|
||||
firmware_cpld_gpio_free(current_info->jtag_en);
|
||||
firmware_cpld_gpio_free(current_info->tdo);
|
||||
if (current_info->jtag_4.pin >= 0) {
|
||||
firmware_cpld_gpio_free(current_info->jtag_1.pin);
|
||||
firmware_cpld_gpio_free(current_info->jtag_2.pin);
|
||||
firmware_cpld_gpio_free(current_info->jtag_3.pin);
|
||||
firmware_cpld_gpio_free(current_info->jtag_4.pin);
|
||||
firmware_cpld_gpio_free(current_info->jtag_5.pin);
|
||||
}
|
||||
|
||||
if (current_info->select >= 0) {
|
||||
firmware_cpld_gpio_free(current_info->select);
|
||||
}
|
||||
|
||||
if (set_gpio_info_flag == 1) {
|
||||
memcpy(current_info, &set_gpio_info, sizeof(firmware_device_info_t));
|
||||
set_gpio_info_flag = 0;
|
||||
}
|
||||
|
||||
dev_debug(firmware_debug(), "%s %d\n", __func__, __LINE__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init_chip_pre(void)
|
||||
{
|
||||
|
||||
dev_debug(firmware_debug(), "%s %d\n", __func__, __LINE__);
|
||||
|
||||
/* to be reset every time when upgrade,solve the use of MAC side GPIO,
|
||||
During the startup process, the MAC terminal will be reset, causing the problem of invalid settings */
|
||||
firmware_cpld_gpio_set_direction(current_info->tdi, 1);
|
||||
firmware_cpld_gpio_set_direction(current_info->tck, 1);
|
||||
firmware_cpld_gpio_set_direction(current_info->tms, 1);
|
||||
firmware_cpld_gpio_set_direction(current_info->jtag_en, 1);
|
||||
if (current_info->select >= 0) {
|
||||
firmware_cpld_gpio_set_direction(current_info->select, 1);
|
||||
}
|
||||
if (current_info->jtag_4.pin >= 0) {
|
||||
firmware_cpld_gpio_set_direction(current_info->jtag_4.pin, 1);
|
||||
firmware_cpld_gpio_set_direction(current_info->jtag_3.pin, 1);
|
||||
firmware_cpld_gpio_set_direction(current_info->jtag_2.pin, 1);
|
||||
firmware_cpld_gpio_set_direction(current_info->jtag_1.pin, 1);
|
||||
firmware_cpld_gpio_set_direction(current_info->jtag_5.pin, 1);
|
||||
}
|
||||
|
||||
firmware_cpld_gpio_set_output_value(current_info->tdi, 1);
|
||||
firmware_cpld_gpio_set_output_value(current_info->tck, 1);
|
||||
firmware_cpld_gpio_set_output_value(current_info->tms, 1);
|
||||
firmware_cpld_gpio_set_output_value(current_info->jtag_en, 1);
|
||||
if (current_info->jtag_4.pin >= 0) {
|
||||
firmware_cpld_gpio_set_output_value(current_info->jtag_1.pin, current_info->jtag_1.val);
|
||||
firmware_cpld_gpio_set_output_value(current_info->jtag_2.pin, current_info->jtag_2.val);
|
||||
firmware_cpld_gpio_set_output_value(current_info->jtag_3.pin, current_info->jtag_3.val);
|
||||
firmware_cpld_gpio_set_output_value(current_info->jtag_4.pin, current_info->jtag_4.val);
|
||||
firmware_cpld_gpio_set_output_value(current_info->jtag_5.pin, current_info->jtag_5.val);
|
||||
}
|
||||
if (current_info->select >= 0) {
|
||||
firmware_cpld_gpio_set_output_value(current_info->select, 1);
|
||||
}
|
||||
|
||||
firmware_cpld_gpio_set_direction(current_info->tdo, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
static int init_chip(int slot)
|
||||
{
|
||||
|
||||
dev_debug(firmware_debug(), "%s %d\n", __func__, __LINE__);
|
||||
|
||||
if (current_info == NULL) {
|
||||
return -1;
|
||||
}
|
||||
init_chip_pre();
|
||||
|
||||
dev_debug(firmware_debug(), "tdi %d %d\n",current_info->tdi, firmware_cpld_gpio_get_value(current_info->tdi));
|
||||
dev_debug(firmware_debug(), "tdo %d %d\n",current_info->tdo, firmware_cpld_gpio_get_value(current_info->tdo));
|
||||
dev_debug(firmware_debug(), "tck %d %d\n",current_info->tck, firmware_cpld_gpio_get_value(current_info->tck));
|
||||
dev_debug(firmware_debug(), "tms %d %d\n",current_info->tms, firmware_cpld_gpio_get_value(current_info->tms));
|
||||
dev_debug(firmware_debug(), " jtag_en:%d %d\n",current_info->jtag_en, firmware_cpld_gpio_get_value(current_info->jtag_en));
|
||||
if (current_info->select >= 0) {
|
||||
dev_debug(firmware_debug(), " select:%d %d\n",current_info->select, firmware_cpld_gpio_get_value(current_info->select));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int finish_chip(int slot)
|
||||
{
|
||||
if (current_info == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
firmware_cpld_gpio_set_output_value(current_info->jtag_en, 0);
|
||||
if (current_info->select >= 0) {
|
||||
firmware_cpld_gpio_set_output_value(current_info->select, 0);
|
||||
}
|
||||
if (current_info->jtag_4.pin >= 0) {
|
||||
firmware_cpld_gpio_set_output_value(current_info->jtag_4.pin, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TDI pull up */
|
||||
static void pull_tdi_up(void)
|
||||
{
|
||||
if (current_info == NULL) {
|
||||
return;
|
||||
}
|
||||
firmware_cpld_gpio_set_output_value(current_info->tdi, 1);
|
||||
}
|
||||
|
||||
/* TDI pull dowm */
|
||||
static void pull_tdi_down(void)
|
||||
{
|
||||
if (current_info == NULL) {
|
||||
return;
|
||||
}
|
||||
firmware_cpld_gpio_set_output_value(current_info->tdi, 0);
|
||||
}
|
||||
|
||||
/* TCK pull up */
|
||||
static void pull_tck_up(void)
|
||||
{
|
||||
if (current_info == NULL) {
|
||||
return;
|
||||
}
|
||||
firmware_cpld_gpio_set_output_value(current_info->tck, 1);
|
||||
}
|
||||
|
||||
/* TCK pull down */
|
||||
static void pull_tck_down(void)
|
||||
{
|
||||
if (current_info == NULL) {
|
||||
return;
|
||||
}
|
||||
firmware_cpld_gpio_set_output_value(current_info->tck, 0);
|
||||
}
|
||||
|
||||
/* TMS pull up */
|
||||
static void pull_tms_up(void)
|
||||
{
|
||||
if (current_info == NULL) {
|
||||
return;
|
||||
}
|
||||
firmware_cpld_gpio_set_output_value(current_info->tms, 1);
|
||||
}
|
||||
|
||||
/* TCK pull dowm */
|
||||
static void pull_tms_down(void)
|
||||
{
|
||||
if (current_info == NULL) {
|
||||
return;
|
||||
}
|
||||
firmware_cpld_gpio_set_output_value(current_info->tms, 0);
|
||||
}
|
||||
|
||||
/* read TDO */
|
||||
static int read_tdo(void)
|
||||
{
|
||||
if (current_info == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return firmware_cpld_gpio_get_value(current_info->tdo);
|
||||
}
|
||||
|
||||
int B6510_fmw_set_gpio_info(firmware_upg_gpio_info_t *info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
dev_debug(firmware_debug(), "set gpio info info %p is null.\n", info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_gpio_info.tdi = info->tdi;
|
||||
set_gpio_info.tck = info->tck;
|
||||
set_gpio_info.tms = info->tms;
|
||||
set_gpio_info.tdo = info->tdo;
|
||||
set_gpio_info.jtag_en = info->jtag_en;
|
||||
set_gpio_info.select= info->select;
|
||||
set_gpio_info.jtag_5.pin = info->jtag_5.pin;
|
||||
set_gpio_info.jtag_4.pin = info->jtag_4.pin;
|
||||
set_gpio_info.jtag_3.pin = info->jtag_3.pin;
|
||||
set_gpio_info.jtag_2.pin = info->jtag_2.pin;
|
||||
set_gpio_info.jtag_1.pin = info->jtag_1.pin;
|
||||
set_gpio_info.jtag_5.val = info->jtag_5.val;
|
||||
set_gpio_info.jtag_4.val = info->jtag_4.val;
|
||||
set_gpio_info.jtag_3.val = info->jtag_3.val;
|
||||
set_gpio_info.jtag_2.val = info->jtag_2.val;
|
||||
set_gpio_info.jtag_1.val = info->jtag_1.val;
|
||||
set_gpio_info_flag = 1;
|
||||
dev_debug(firmware_debug(), "set gpio info[tdi:%d tck:%d tms:%d tdo:%d jtag_en:%d select:%d].\n",
|
||||
info->tdi, info->tck, info->tms, info->tdo, info->jtag_en, info->select);
|
||||
return 0;
|
||||
}
|
||||
|
||||
firmware_cpld_t fmw_cpld0 = {
|
||||
.devname = "firmware_cpld_ispvme0",
|
||||
.slot = 1,
|
||||
.chip_index = 1,
|
||||
.is_used = 1,
|
||||
.tck_delay = 60,
|
||||
.pull_tdi_up = pull_tdi_up,
|
||||
.pull_tdi_down = pull_tdi_down,
|
||||
.pull_tck_up = pull_tck_up,
|
||||
.pull_tck_down = pull_tck_down,
|
||||
.pull_tms_up = pull_tms_up,
|
||||
.pull_tms_down = pull_tms_down,
|
||||
.read_tdo = read_tdo,
|
||||
.init_cpld = init_cpld,
|
||||
.init_chip = init_chip,
|
||||
.finish_chip = finish_chip,
|
||||
.finish_cpld = finish_cpld,
|
||||
.get_version = NULL,
|
||||
};
|
||||
|
||||
static void cpld_release(struct device *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static struct platform_device cpld = {
|
||||
.name = "firmware_cpld_ispvme",
|
||||
.id = 0,
|
||||
.num_resources = 0,
|
||||
.dev = {
|
||||
.release = cpld_release,
|
||||
}
|
||||
};
|
||||
|
||||
extern void set_currrent_cpld_info(firmware_cpld_t *info);
|
||||
extern int dfd_get_my_card_type(void);
|
||||
|
||||
int fmw_cpld_product_init(void)
|
||||
{
|
||||
current_info = NULL;
|
||||
#if 0
|
||||
int dev_type;
|
||||
int i;
|
||||
|
||||
dev_type = drv_get_my_dev_type();
|
||||
if (dev_type < 0) {
|
||||
printk(KERN_ERR "Failed to get device type, when upgrade cpld.\n");
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(cpld_info)/sizeof(cpld_info[0]); i++) {
|
||||
if (cpld_info[i].type == dev_type) {
|
||||
current_info = &cpld_info[i];
|
||||
printk(KERN_ERR "device type 0x%x match i %d.\n", dev_type, i);
|
||||
printk(KERN_ERR "tdi[%d] tck[%d] tms[%d] tdo[%d] jtat_en[%d].\n", current_info->tdi,
|
||||
current_info->tck, current_info->tms, current_info->tdo, current_info->jtag_en);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (current_info == NULL) {
|
||||
current_info = &default_cpld_info;
|
||||
}
|
||||
|
||||
platform_device_register(&cpld);
|
||||
fmw_cpld_upg_copy_firmware_info(&fmw_cpld0);
|
||||
|
||||
/* fmw_cpld0.init_cpld(); */
|
||||
set_currrent_cpld_info(&fmw_cpld0);
|
||||
|
||||
fmw_cpld_reg_gpio_info_set_func(B6510_fmw_set_gpio_info);
|
||||
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
void fmw_cpld_product_exit(void)
|
||||
{
|
||||
platform_device_unregister(&cpld);
|
||||
return;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
#ifndef __CONFIG_H__
|
||||
#define __CONFIG_H__
|
||||
|
||||
#include <firmware_cpld_ispvme.h>
|
||||
|
||||
#define JTAG_TDI (32)
|
||||
#define JTAG_TDO (67)
|
||||
#define JTAG_TCK (65)
|
||||
#define JTAG_TMS (6)
|
||||
#define JTAG_EN (50)
|
||||
|
||||
typedef struct firmware_device_info_s {
|
||||
int type;
|
||||
int tdi;
|
||||
int tck;
|
||||
int tms;
|
||||
int tdo;
|
||||
int jtag_en;
|
||||
int select;
|
||||
gpio_group_t jtag_5;
|
||||
gpio_group_t jtag_4;
|
||||
gpio_group_t jtag_3;
|
||||
gpio_group_t jtag_2;
|
||||
gpio_group_t jtag_1;
|
||||
int cmic_start_gpio;
|
||||
int cmic_end_gpio;
|
||||
} firmware_device_info_t;
|
||||
|
||||
#endif /* __CONFIG_H__ */
|
@ -1,39 +0,0 @@
|
||||
include $(top_srcdir)/Rules.mk
|
||||
|
||||
OBJ = firmware_app_ispvme.o debug_ispvme.o hardware.o ispvm_ui.o ivm_core.o dfd_fpga_pkt.o dfd_fpga_upg.o dfd_fpga_debug.o
|
||||
LIB += $(BUILD_CFALGS) $(BUILD_LDFLAGS) -lpthread -lreadline -lncurses
|
||||
ifdef ENABLE_GCOV
|
||||
ifeq ($(ENABLE_GCOV), y)
|
||||
LIB += -lgcov
|
||||
endif
|
||||
endif # ENABLE_GCOV
|
||||
APP = firmware_upgrade
|
||||
BUILD_DIR = tmp
|
||||
ELF_FILE = $(BUILD_DIR)/$(APP)
|
||||
MAP_FILE = $(BUILD_DIR)/$(APP).map.sym
|
||||
INCLUDE = -Iinclude
|
||||
|
||||
.PHONY: build
|
||||
build:make-dir $(addprefix $(BUILD_DIR)/,$(OBJ))
|
||||
$(CC) -o $(ELF_FILE) $(addprefix $(BUILD_DIR)/,$(OBJ)) $(LINKFLAGS) $(LIB)
|
||||
$(NM) $(ELF_FILE) | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' \
|
||||
| sort > $(MAP_FILE)
|
||||
@if [ ! -d $(common_out_put_dir) ]; then mkdir -p $(common_out_put_dir) ;fi
|
||||
cp -p $(ELF_FILE) $(common_out_put_dir)
|
||||
|
||||
# build
|
||||
.PHONY: make-dir
|
||||
make-dir:
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
|
||||
$(BUILD_DIR)/%.o:%.c
|
||||
$(CC) -c $(CFLAGS) $(INCLUDE) $< -o $@
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
echo "firmware_upgrade install success."
|
||||
cp -p $(ELF_FILE) $(common_out_put_dir)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
@ -1,28 +0,0 @@
|
||||
#ifndef __COMMON_H__
|
||||
#define __COMMON_H__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#define FIRMWARE_TYPE 'F'
|
||||
#define FIRMWARE_JTAG_TDI _IOR(FIRMWARE_TYPE, 0, char)
|
||||
#define FIRMWARE_JTAG_TDO _IOR(FIRMWARE_TYPE, 1, char)
|
||||
#define FIRMWARE_JTAG_TCK _IOR(FIRMWARE_TYPE, 2, char)
|
||||
#define FIRMWARE_JTAG_TMS _IOR(FIRMWARE_TYPE, 3, char)
|
||||
#define FIRMWARE_JTAG_EN _IOR(FIRMWARE_TYPE, 4, char)
|
||||
#define FIRMWARE_SET_DEBUG_ON _IOW(FIRMWARE_TYPE, 5, int) /* debug on */
|
||||
#define FIRMWARE_SET_DEBUG_OFF _IOW(FIRMWARE_TYPE, 6, int) /* debug off */
|
||||
#define FIRMWARE_SET_GPIO_INFO _IOR(FIRMWARE_TYPE, 7, int) /* set GPIO pin configuration */
|
||||
|
||||
#define JTAG_TDI (1)
|
||||
#define JTAG_TDO (2)
|
||||
#define JTAG_TCK (3)
|
||||
#define JTAG_TMS (4)
|
||||
#define JTAG_ENABLE (5)
|
||||
#define JTAG_TRST (6)
|
||||
|
||||
#endif
|
@ -1,67 +0,0 @@
|
||||
/**
|
||||
* Copyright(C) 2013 Ragile Network. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* debug.c
|
||||
*
|
||||
* firmware upgrade debug control
|
||||
*
|
||||
* Original Author : support <support@ragile.com>2013-10-25
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
#include <debug_ispvme.h>
|
||||
|
||||
/**
|
||||
* firmware_upgrade_debug:handle debug switch
|
||||
*
|
||||
* analyse file /tmp/firmware_upgrade_debug,return the information correspoding to debug
|
||||
*
|
||||
* return:return DEBUG_OFF when debug off,return DEBUG_ON when debug on,return DEBUG_IGNORE in other cases
|
||||
*/
|
||||
int firmware_upgrade_debug(void)
|
||||
{
|
||||
int size;
|
||||
FILE *fp;
|
||||
char debug_info[DEBUG_INFO_LEN] = {0};
|
||||
|
||||
fp = fopen(DEBUG_FILE, "r");
|
||||
if (fp == NULL) {
|
||||
return DEBUG_IGNORE;
|
||||
}
|
||||
|
||||
size = fread(debug_info, DEBUG_INFO_LEN - 1, 1, fp);
|
||||
if (size < 0) {
|
||||
fclose(fp);
|
||||
return DEBUG_IGNORE;
|
||||
}
|
||||
|
||||
if (strncmp(debug_info, DEBUG_ON_INFO, 1) == 0) {
|
||||
fclose(fp);
|
||||
return DEBUG_APP_ON;
|
||||
}
|
||||
|
||||
if (strncmp(debug_info, DEBUG_ON_KERN, 1) == 0) {
|
||||
fclose(fp);
|
||||
return DEBUG_KERN_ON;
|
||||
}
|
||||
|
||||
if (strncmp(debug_info, DEBUG_ON_ALL, 1) == 0) {
|
||||
fclose(fp);
|
||||
return DEBUG_ALL_ON;
|
||||
}
|
||||
|
||||
if (strncmp(debug_info, DEBUG_OFF_INFO, 1) == 0) {
|
||||
fclose(fp);
|
||||
return DEBUG_OFF;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return DEBUG_IGNORE;
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright(C) 2001-2013 Ragile Network. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* dfd_debug.c
|
||||
*
|
||||
* Function:Device framework driver debugging interface
|
||||
*
|
||||
* History
|
||||
* v1.0 support <support@ragile.com> 2013-10-25 Initial version.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dfd_fpga_debug.h"
|
||||
|
||||
#undef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(a) (sizeof(a) /sizeof((a)[0]))
|
||||
/* Debug switch storage of dfd module */
|
||||
int g_dfd_fpga_debug = 0x0;
|
||||
|
||||
/**
|
||||
* dfd_fpga_pkt_debug_set - Debug switch setting interface of dfd module
|
||||
* @type: Types of debugging information
|
||||
* @enable: enable/Disable debugging information
|
||||
*
|
||||
* return 0 if success, otherwise reuturn -1.
|
||||
*/
|
||||
static int dfd_fpga_pkt_debug_set(int type, int enable)
|
||||
{
|
||||
|
||||
if (type >= DFD_DBG_CNT || type < 0) {
|
||||
DFD_ERROR("unknow dfd debug type=%d\n", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
g_dfd_fpga_debug |= 1U << type;
|
||||
} else {
|
||||
g_dfd_fpga_debug &= ~(1U << type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dfd_fpga_open_debug(int val)
|
||||
{
|
||||
if (val == 1) {
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 1);
|
||||
} else if (val == 2) {
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 1);
|
||||
} else if (val == 3) {
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_DBG, 1);
|
||||
} else if (val == 4) {
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_DBG, 1);
|
||||
} else {
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 0);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 0);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 0);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 0);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_DBG, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void dfd_fpga_debug_init(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[10] = {0};
|
||||
|
||||
fp = fopen(DFD_DEBUG_FILE, "r");
|
||||
if (fp != NULL) {
|
||||
if (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
if (strstr(buf, DFD_DEBUG_SET_NO_WARN) != NULL) {
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 0);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 0);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 0);
|
||||
} else if (strstr(buf, DFD_DEBUG_SET_NO_VBOSE) != NULL) {
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 0);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 0);
|
||||
} else if (strstr(buf, DFD_DEBUG_SET_NO_FLOCK_VBOSE) != NULL) {
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 0);
|
||||
} else if (strstr(buf, DFD_DEBUG_SET_ALL) != NULL) {
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_ERR, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_WARN, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_VBOSE, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 1);
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_DBG, 1);
|
||||
} else if (strstr(buf, DFD_DEBUG_SET_DBG) != NULL) {
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_DBG_DBG, 1);
|
||||
} else if (strstr(buf, DFD_DEBUG_SET_FLOCK) != NULL) {
|
||||
(void)dfd_fpga_pkt_debug_set(DFD_FLOCK_DBG_VBOSE, 1);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
#ifndef _DFD_FPGA_DEBUG_H_
|
||||
#define _DFD_FPGA_DEBUG_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DFD_DEBUG_FILE "/sbin/.dfd_debug_flag"
|
||||
|
||||
#define DFD_DEBUG_SET_NO_WARN "0x1"
|
||||
#define DFD_DEBUG_SET_NO_VBOSE "0x3"
|
||||
#define DFD_DEBUG_SET_NO_FLOCK_VBOSE "0x7"
|
||||
#define DFD_DEBUG_SET_ALL "0xf"
|
||||
#define DFD_DEBUG_SET_DBG "0xd"
|
||||
#define DFD_DEBUG_SET_FLOCK "0xe"
|
||||
#define mem_clear(data, size) memset((data), 0, (size))
|
||||
|
||||
#define DFD_DEBUG_CHECK(type) (g_dfd_fpga_debug & (1U << (type)))
|
||||
|
||||
#define DFD_ERROR(fmt, args...) do { \
|
||||
if (DFD_DEBUG_CHECK(DFD_DBG_ERR)) { \
|
||||
printf("[%s-%s]:<File:%s, Func:%s, Line:%d>\n" fmt, "DFD", "err", \
|
||||
__FILE__, __FUNCTION__, __LINE__, ##args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DFD_WARN(fmt, args...) do { \
|
||||
if (DFD_DEBUG_CHECK(DFD_DBG_WARN)) { \
|
||||
printf("[%s-%s]:<File:%s, Func:%s, Line:%d>\n" fmt, "DFD", "warn", \
|
||||
__FILE__, __FUNCTION__, __LINE__, ##args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DFD_VERBOS(fmt, args...) do { \
|
||||
if (DFD_DEBUG_CHECK(DFD_DBG_VBOSE)) { \
|
||||
printf("[%s-%s]:<File:%s, Func:%s, Line:%d>\n" fmt, "DFD", "vbose", \
|
||||
__FILE__, __FUNCTION__, __LINE__, ##args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DFD_FLOCK_VERBOS(fmt, args...) do { \
|
||||
if (DFD_DEBUG_CHECK(DFD_FLOCK_DBG_VBOSE)) { \
|
||||
printf("[%s-%s]:<File:%s, Func:%s, Line:%d>\n" fmt, "DFD", "flock_vbose", \
|
||||
__FILE__, __FUNCTION__, __LINE__, ##args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DFD_DBG(fmt, args...) do { \
|
||||
if (DFD_DEBUG_CHECK(DFD_DBG_DBG)) { \
|
||||
printf("" fmt,\
|
||||
##args); \
|
||||
} \
|
||||
} while (0)
|
||||
/* define the type of debugging information */
|
||||
typedef enum {
|
||||
DFD_DBG_ERR,
|
||||
DFD_DBG_WARN,
|
||||
DFD_DBG_VBOSE,
|
||||
DFD_FLOCK_DBG_VBOSE,
|
||||
DFD_DBG_DBG,
|
||||
DFD_DBG_CNT
|
||||
} DFD_DEBUG_TYPE_E;
|
||||
|
||||
extern int g_dfd_fpga_debug;
|
||||
|
||||
int dfd_fpga_debug_set(int type, int enable);
|
||||
void dfd_fpga_open_debug(int val);
|
||||
void dfd_fpga_debug_init(void);
|
||||
|
||||
#endif
|
@ -1,321 +0,0 @@
|
||||
/*
|
||||
* Copyright(C) 2001-2012 Ragile Network. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* dfd_fpga_pkt.c
|
||||
*
|
||||
* FPGA message interaction related interface
|
||||
*
|
||||
* History
|
||||
* v1.0 support <support@ragile.com> 2013-10-25 Initial version.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <pthread.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "dfd_fpga_pkt.h"
|
||||
#include "dfd_fpga_debug.h"
|
||||
|
||||
#define DFD_FPGA_FAC_MODE_CONFIG_FILE "/tmp/.factory_disabale_cli_tty"
|
||||
#if 1
|
||||
#define DFD_FPGA_PKT_SEND_PKT_TO_FRAME
|
||||
#endif
|
||||
|
||||
void dfd_fpga_pkt_print(uint8_t *buf, int buf_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < buf_len; i++) {
|
||||
if ((i % 16) == 0) {
|
||||
DFD_DBG("\n");
|
||||
}
|
||||
DFD_DBG("%02x ", buf[i]);
|
||||
}
|
||||
|
||||
DFD_DBG("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned int littel_endian_byte_to_word32(uint8_t *byte_buf, int len)
|
||||
{
|
||||
uint8_t tmp_buf[4];
|
||||
unsigned int word;
|
||||
|
||||
word = 0;
|
||||
|
||||
mem_clear(tmp_buf, 4);
|
||||
memcpy(tmp_buf, byte_buf, len < 4 ? len : 4);
|
||||
|
||||
word = tmp_buf[0] | (tmp_buf[1] << 8) | (tmp_buf[2] << 16) | (tmp_buf[3] << 24);
|
||||
|
||||
return word;
|
||||
}
|
||||
|
||||
static int littel_endian_word32_to_byte(uint8_t *byte_buf, int len, unsigned int word)
|
||||
{
|
||||
uint8_t tmp_buf[4];
|
||||
int ret;
|
||||
|
||||
if (len < 4) {
|
||||
DFD_ERROR("Not enough buf, word32 to byte: len[%d], word[0x%x]\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mem_clear(tmp_buf, 4);
|
||||
tmp_buf[0] = word & 0xff;
|
||||
tmp_buf[1] = (word >> 8) & 0xff;
|
||||
tmp_buf[2] = (word >> 16) & 0xff;
|
||||
tmp_buf[3] = (word >> 24) & 0xff;
|
||||
|
||||
memcpy(byte_buf, tmp_buf, 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int open_pci_dev(dfd_pci_dev_priv_t *pci_priv, int is_cfg)
|
||||
{
|
||||
int file, ret;
|
||||
char filename[DFD_PCI_MAX_NAME_SIZE];
|
||||
|
||||
if (is_cfg) {
|
||||
ret = snprintf(filename, DFD_PCI_MAX_NAME_SIZE,
|
||||
"/sys/class/pci_bus/%04x:%02x/device/%04x:%02x:%02x.%d/config",
|
||||
0, pci_priv->pcibus, 0, pci_priv->pcibus, pci_priv->slot, pci_priv->fn);
|
||||
} else {
|
||||
ret = snprintf(filename, DFD_PCI_MAX_NAME_SIZE,
|
||||
"/sys/class/pci_bus/%04x:%02x/device/%04x:%02x:%02x.%d/resource%d",
|
||||
0, pci_priv->pcibus, 0, pci_priv->pcibus, pci_priv->slot, pci_priv->fn,
|
||||
pci_priv->bar);
|
||||
}
|
||||
|
||||
filename[ret] = '\0';
|
||||
if ((file = open(filename, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
|
||||
DFD_ERROR("Error: Could not open file %s\n", filename);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* dfd_fpga_buf_read - provide FPGA write register interface (address must be four-byte aligned)
|
||||
* @dst: The data structure of sslot and unit corresponding to the target chip
|
||||
* @addr: address (four-byte alignment). For the byte alignment required by the specific FPGA address, please refer to the FPGA manual
|
||||
* @buf: Buffer for reading data
|
||||
* @wr_len: the length of reading data,please refer to the FPGA manual for the length of the specific FPGA address requirements
|
||||
* return: return if success,else return -1
|
||||
*/
|
||||
int dfd_fpga_pci_read(dfd_pci_dev_priv_t *pci_priv, int offset, uint8_t *buf, int rd_len)
|
||||
{
|
||||
int ret, fd;
|
||||
unsigned int data;
|
||||
uint8_t *ptr, *ptr_data;
|
||||
struct stat sb;
|
||||
int i;
|
||||
int len, align;
|
||||
|
||||
if ((pci_priv == NULL) || (buf == NULL)) {
|
||||
DFD_ERROR("pci_prive or read buf is null.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((pci_priv->align < 1) || (offset & (pci_priv->align - 1)) || (rd_len & (pci_priv->align - 1))) {
|
||||
DFD_ERROR("offset[%d] or rd_len[%d] don't align[%d].\n", offset, rd_len, pci_priv->align);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((fd = open_pci_dev(pci_priv, 0)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ret = fstat(fd, &sb)) == -1) {
|
||||
DFD_ERROR("Error: Could not fstat : %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset + rd_len >= sb.st_size) {
|
||||
DFD_ERROR("Error: offset is out of range\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ptr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, 0)) == MAP_FAILED) {
|
||||
DFD_ERROR("Error: Could not mmap : %s or resource is IO\n", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
align = pci_priv->align;
|
||||
len = rd_len;
|
||||
ret = 0;
|
||||
i = 0;
|
||||
ptr_data = ptr + offset;
|
||||
|
||||
while((i < len) && (ret == 0)){
|
||||
if (align == 4) {
|
||||
data = *((volatile unsigned int *)(ptr_data + i));
|
||||
ret = littel_endian_word32_to_byte(buf + i, len - i, data);
|
||||
i += 4;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
munmap(ptr, sb.st_size);
|
||||
close(fd);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* dfd_fpga_buf_write -provide FPGA write register interface (address must be four-byte aligned)
|
||||
* @dst: The data structure of sslot and unit corresponding to the target chip
|
||||
* @addr: address (four-byte alignment). For the byte alignment required by the specific FPGA address, please refer to the FPGA manual
|
||||
* @buf: Buffer for reading data
|
||||
* @wr_len: the length of reading data,please refer to the FPGA manual for the length of the specific FPGA address requirements
|
||||
* return: return if success,else return -1
|
||||
*/
|
||||
|
||||
int dfd_fpga_pci_write(dfd_pci_dev_priv_t *pci_priv, int offset, uint8_t *buf, int wr_len)
|
||||
{
|
||||
int ret, fd;
|
||||
unsigned int data;
|
||||
uint8_t *ptr, *ptr_data;
|
||||
struct stat sb;
|
||||
int i;
|
||||
int len, align;
|
||||
|
||||
if ((pci_priv == NULL) || (buf == NULL)) {
|
||||
DFD_ERROR("pci_prive or write buf is null.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((pci_priv->align < 1) || (offset & (pci_priv->align - 1)) || (wr_len & (pci_priv->align - 1))) {
|
||||
DFD_ERROR("offset[%d] or rd_len[%d] don't align[%d].\n", offset, wr_len, pci_priv->align);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((fd = open_pci_dev(pci_priv, 0)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ret = fstat(fd, &sb)) == -1) {
|
||||
DFD_ERROR("Error: Could not fstat : %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset + wr_len >= sb.st_size) {
|
||||
DFD_ERROR("Error: offset is out of range\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ptr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, 0)) == MAP_FAILED) {
|
||||
DFD_ERROR("Error: Could not mmap : %s or resource is IO\n", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
align = pci_priv->align;
|
||||
len = wr_len;
|
||||
ret = 0;
|
||||
i = 0;
|
||||
ptr_data = ptr + offset;
|
||||
|
||||
while((i < len) && (ret == 0)){
|
||||
if (align == 4) {
|
||||
data = littel_endian_byte_to_word32(buf + i,len - i);
|
||||
*((volatile unsigned int *)(ptr_data + i)) = data;
|
||||
i += 4;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
munmap(ptr, sb.st_size);
|
||||
close(fd);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* dfd_fpga_read_word -provide FPGA read register interface (address must be four-byte aligned)
|
||||
* @addr: address (four-byte alignment)
|
||||
* @val: the returned number of reading
|
||||
* return: return 0 if success,else return failure
|
||||
*/
|
||||
int dfd_fpga_read_word(dfd_pci_dev_priv_t *pci_priv, int addr, int *val)
|
||||
{
|
||||
int ret, i;
|
||||
uint8_t tmp[DFD_FPGA_PKT_WORD_LEN];
|
||||
|
||||
if ((pci_priv == NULL) || (val == NULL) || (addr & 0x03)) {
|
||||
DFD_ERROR("Input para invalid pci_priv %p val %p addr 0x%x.\n", pci_priv, val, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = dfd_fpga_pci_read(pci_priv, addr, tmp, DFD_FPGA_PKT_WORD_LEN);
|
||||
if (ret) {
|
||||
DFD_ERROR("dfd_fpga_pci_read addr 0x%x failed ret %d.\n", addr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = littel_endian_byte_to_word32(tmp,DFD_FPGA_PKT_WORD_LEN);
|
||||
for (i = 0; i < DFD_FPGA_PKT_WORD_LEN; i++) {
|
||||
DFD_VERBOS("tmp[%d]: 0x%x.\n", i, tmp[i]);
|
||||
}
|
||||
DFD_VERBOS("dfd_fpga_read_word addr 0x%x val 0x%x.\n", addr, *val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dfd_fpga_write_word -provide FPGA write register interface (address must be four-byte aligned)
|
||||
* @addr: address (four-byte alignment)
|
||||
* @val: Data written
|
||||
* return: return 0 if success,else return failure
|
||||
*/
|
||||
int dfd_fpga_write_word(dfd_pci_dev_priv_t *pci_priv, int addr, int val)
|
||||
{
|
||||
int ret, i;
|
||||
uint8_t tmp[DFD_FPGA_PKT_WORD_LEN];
|
||||
|
||||
if ((pci_priv == NULL) || (addr & 0x03)) {
|
||||
DFD_ERROR("Input para invalid pci_priv %p addr 0x%x.\n", pci_priv, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
littel_endian_word32_to_byte(tmp, DFD_FPGA_PKT_WORD_LEN, val);
|
||||
for (i = 0; i < DFD_FPGA_PKT_WORD_LEN; i++) {
|
||||
DFD_VERBOS("tmp[%d]: 0x%x.\n", i, tmp[i]);
|
||||
}
|
||||
|
||||
ret = dfd_fpga_pci_write(pci_priv, addr, tmp, DFD_FPGA_PKT_WORD_LEN);
|
||||
if (ret) {
|
||||
DFD_ERROR("dfd_fpga_pci_write addr 0x%x failed ret %d.\n", addr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DFD_VERBOS("dfd_fpga_write_word addr 0x%x val 0x%x.\n", addr, val);
|
||||
return 0;
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
#ifndef __DFD_FPGA_PKT_H__
|
||||
#define __DFD_FPGA_PKT_H__
|
||||
|
||||
typedef enum dfd_fpga_pkt_op_type_e {
|
||||
DFD_FPGA_PKT_OP_TYPE_READ = 0, /* read */
|
||||
DFD_FPGA_PKT_OP_TYPE_WRITE = 1, /* write */
|
||||
DFD_FPGA_PKT_OP_TYPE_END,
|
||||
} dfd_fpga_pkt_op_type_t;
|
||||
|
||||
typedef enum dfd_fpga_pkt_ack_type_e {
|
||||
DFD_FPGA_PKT_ACK_TYPE_NO_ERROR = 0, /* successful operation */
|
||||
DFD_FPGA_PKT_ACK_TYPE_FCS_ERROR = 1, /* operation FCS check error */
|
||||
DFD_FPGA_PKT_ACK_TYPE_FAIL_ERROR = 2, /* operation failed */
|
||||
DFD_FPGA_PKT_ACK_TYPE_END,
|
||||
} dfd_fpga_pkt_ack_type_t;
|
||||
|
||||
typedef enum dfd_rv_s {
|
||||
DFD_RV_OK = 0,
|
||||
DFD_RV_INIT_ERR = 1,
|
||||
DFD_RV_SLOT_INVALID = 2,
|
||||
DFD_RV_MODE_INVALID = 3,
|
||||
DFD_RV_MODE_NOTSUPPORT = 4,
|
||||
DFD_RV_TYPE_ERR = 5,
|
||||
DFD_RV_DEV_NOTSUPPORT = 6,
|
||||
DFD_RV_DEV_FAIL = 7,
|
||||
DFD_RV_INDEX_INVALID = 8,
|
||||
DFD_RV_NO_INTF = 9,
|
||||
DFD_RV_NO_NODE = 10,
|
||||
DFD_RV_NODE_FAIL = 11,
|
||||
} dfd_rv_t;
|
||||
|
||||
typedef struct dfd_pci_dev_priv_s {
|
||||
int pcibus;
|
||||
int slot;
|
||||
int fn;
|
||||
int bar;
|
||||
int offset;
|
||||
int times;
|
||||
int align;
|
||||
int fpga_upg_base;
|
||||
}dfd_pci_dev_priv_t;
|
||||
|
||||
#define DFD_PCI_MAX_NAME_SIZE 256
|
||||
|
||||
#define DFD_MAX_FPGA_NUM (8)
|
||||
#define DFD_FPGA_PKT_WORD_LEN (4)
|
||||
|
||||
#define DFD_FPGA_PKT_MAC_LEN (6)
|
||||
#define DFD_FPGA_PKT_PAYLOAD_WORD_DATA_LEN (4)
|
||||
|
||||
#define DFD_FPGA_PKT_WORD_RW_LEN (1)/* for each access, according to 1 WORD, 4 bytes to access FPGA */
|
||||
|
||||
#define DFD_FPGA_PKT_ETYPE (0xfff9)
|
||||
|
||||
#define DFD_FPGA_PKT_PAYLOAD_ADDR_LEN (4)
|
||||
#define DFD_FPGA_PKT_PAYLOAD_LENGTH_LEN (2)
|
||||
|
||||
#define DFD_FPGA_PKT_PAYLOAD_ADDR_OFFSET (0)
|
||||
#define DFD_FPGA_PKT_PAYLOAD_LENGTH_OFFSET (DFD_FPGA_PKT_PAYLOAD_ADDR_LEN)
|
||||
#define DFD_FPGA_PKT_PAYLOAD_DATA_OFFSET ((DFD_FPGA_PKT_PAYLOAD_ADDR_LEN) + (DFD_FPGA_PKT_PAYLOAD_LENGTH_LEN))
|
||||
|
||||
#define DFD_FPGA_PKT_GET_DATA(payload) (((uint8_t*)(payload)) + DFD_FPGA_PKT_PAYLOAD_DATA_OFFSET)
|
||||
#define DFD_FPGA_PKT_GET_PAYLOAD_LEN(len) ((DFD_FPGA_PKT_PAYLOAD_ADDR_LEN) + (DFD_FPGA_PKT_PAYLOAD_LENGTH_LEN) + (len))
|
||||
|
||||
#pragma pack (1)
|
||||
typedef struct dfd_fpga_pkt_payload_s {
|
||||
uint32_t addr; /* the address of reading and writting */
|
||||
uint16_t length; /* the length of reading and writting */
|
||||
uint32_t data; /* read and write data (for read operations, you don't need to care about this field) */
|
||||
} dfd_fpga_pkt_payload_t;
|
||||
|
||||
typedef struct dfd_fpga_pkt_rd_payload_s {
|
||||
uint32_t addr; /* the address of reading */
|
||||
uint16_t length; /* the length of reading */
|
||||
} dfd_fpga_pkt_rd_payload_t;
|
||||
#pragma pack ()
|
||||
|
||||
typedef enum fpga_version_e {
|
||||
FPGA_VER_00 = 0x00,
|
||||
FPGA_VER_01,
|
||||
FPGA_VER_02,
|
||||
FPGA_VER_03,
|
||||
FPGA_VER_04,
|
||||
FPGA_VER_05,
|
||||
FPGA_VER_06,
|
||||
} fpga_version_t;
|
||||
|
||||
int dfd_fpga_upg_init(void);
|
||||
int dfd_fpga_write_word(dfd_pci_dev_priv_t *pci_priv, int addr, int val);
|
||||
int dfd_fpga_read_word(dfd_pci_dev_priv_t *pci_priv, int addr, int *val);
|
||||
int dfd_fpga_pci_write(dfd_pci_dev_priv_t *pci_priv, int offset, uint8_t *buf, int wr_len);
|
||||
int dfd_fpga_pci_read(dfd_pci_dev_priv_t *pci_priv, int offset, uint8_t *buf, int rd_len);
|
||||
extern int drv_get_my_dev_type(void);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,906 +0,0 @@
|
||||
/**
|
||||
* Copyright(C) 2013 Ragile Network. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* firmware_app.c
|
||||
|
||||
* firmware upgrade
|
||||
* v1.0 support <support@ragile.com> 2013-10-25 Initial version.
|
||||
*/
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#if 0
|
||||
#include <ssa/lib/ssa_dfd_intf.h>
|
||||
#include <autoconf.h>
|
||||
#endif
|
||||
#include <firmware_app_ispvme.h>
|
||||
static firmware_card_info_t g_card_info[] = {
|
||||
{
|
||||
.dev_type = RA_B6010_48GT4X,
|
||||
.slot_num = 1,
|
||||
.card_name = "RA_B6010_48GT4X",
|
||||
.gpio_info = {
|
||||
/* slot 0 */
|
||||
{
|
||||
.tdi = 507,
|
||||
.tck = 505,
|
||||
.tms = 506,
|
||||
.tdo = 508,
|
||||
.jtag_en = 504,
|
||||
.select = -1,
|
||||
.jtag_5 = GPIO(-1, 0,1)
|
||||
.jtag_4 = GPIO(-1, 0,1)
|
||||
.jtag_3 = GPIO(-1, 1,1)
|
||||
.jtag_2 = GPIO(-1, 0,1)
|
||||
.jtag_1 = GPIO(-1, 1,1)
|
||||
},
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
.dev_type = RA_B6010_48GT4X_R,
|
||||
.slot_num = 1,
|
||||
.card_name = "RA_B6010_48GT4X_R",
|
||||
.gpio_info = {
|
||||
/* slot 0 */
|
||||
{
|
||||
.tdi = 507,
|
||||
.tck = 505,
|
||||
.tms = 506,
|
||||
.tdo = 508,
|
||||
.jtag_en = 504,
|
||||
.select = -1,
|
||||
.jtag_5 = GPIO(-1, 0,1)
|
||||
.jtag_4 = GPIO(-1, 0,1)
|
||||
.jtag_3 = GPIO(-1, 1,1)
|
||||
.jtag_2 = GPIO(-1, 0,1)
|
||||
.jtag_1 = GPIO(-1, 1,1)
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static int is_debug_on;
|
||||
static int dfd_my_type = 0;
|
||||
|
||||
#if 0
|
||||
#if defined(CONFIG_FRM_PRODUCT_NAME)
|
||||
#define CONFIG_RAGILE_PRODUCT_NAME CONFIG_FRM_PRODUCT_NAME
|
||||
#else
|
||||
#define CONFIG_RAGILE_PRODUCT_NAME "card"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DFD_TYPE_FILE "/sys/module/ragile_common/parameters/dfd_my_type"
|
||||
#define DFD_TYPE_BUFF_SIZE (256)
|
||||
|
||||
static int is_vme_file(char *file_name)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
tmp = strchr(file_name, '.');
|
||||
if (strcmp(tmp, ".bin") == 0) {
|
||||
return 0;
|
||||
} else if (strcmp(tmp, ".vme") == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int drv_get_my_dev_type(void)
|
||||
{
|
||||
int type;
|
||||
int fd;
|
||||
char rbuf[DFD_TYPE_BUFF_SIZE];
|
||||
int read_len;
|
||||
|
||||
if (dfd_my_type != 0) {
|
||||
dbg_print(is_debug_on, "my_type = 0x%x\r\n", dfd_my_type);
|
||||
return dfd_my_type;
|
||||
}
|
||||
|
||||
fd = open(DFD_TYPE_FILE, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
dbg_print(is_debug_on, "can't open device %s.\r\n", DFD_TYPE_FILE);
|
||||
return RA_B6010_48GT4X; /* Avoid B6510 to obtain different device types */
|
||||
}
|
||||
|
||||
mem_clear(rbuf, DFD_TYPE_BUFF_SIZE);
|
||||
type = 0;
|
||||
read_len = read(fd, rbuf, DFD_TYPE_BUFF_SIZE - 1);
|
||||
if (read_len > 0) {
|
||||
type = strtoul(rbuf, NULL, 0);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
dfd_my_type = type;
|
||||
|
||||
dbg_print(is_debug_on, "read dfd type file is %s read_len %d, dfd_my_type 0x%x\n", rbuf, read_len, dfd_my_type);
|
||||
return dfd_my_type;
|
||||
}
|
||||
|
||||
firmware_card_info_t* firmware_get_card_info(int dev_type)
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
|
||||
size = (sizeof(g_card_info) /sizeof((g_card_info)[0]));
|
||||
|
||||
dbg_print(is_debug_on, "Enter dev_type 0x%x size %d.\n", dev_type, size);
|
||||
for (i = 0; i < size; i++) {
|
||||
if (g_card_info[i].dev_type == dev_type) {
|
||||
dbg_print(is_debug_on, "match dev_type 0x%x.\n", dev_type);
|
||||
return &g_card_info[i];
|
||||
}
|
||||
}
|
||||
|
||||
dbg_print(is_debug_on, "dismatch dev_type 0x%x.\n", dev_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int firmware_get_card_name(char *name, int len)
|
||||
{
|
||||
int dev_type;
|
||||
firmware_card_info_t *info;
|
||||
|
||||
dbg_print(is_debug_on, "Enter len %d.\n", len);
|
||||
dev_type = drv_get_my_dev_type();
|
||||
if (dev_type < 0) {
|
||||
dbg_print(is_debug_on, "drv_get_my_dev_type failed ret %d.\n", dev_type);
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
info = firmware_get_card_info(dev_type);
|
||||
if (info == NULL) {
|
||||
dbg_print(is_debug_on, "firmware_get_card_info dev_type %d failed.\n", dev_type );
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
strncpy(name, info->card_name, len - 1);
|
||||
dbg_print(is_debug_on, "Leave dev_type 0x%x name %s, info->name %s.\n", dev_type,
|
||||
name, info->card_name);
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
int get_debug_value(void)
|
||||
{
|
||||
return is_debug_on;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* each device implements its own corresponding interface */
|
||||
int __attribute__ ((weak)) firmware_get_card_name(char *name, int len)
|
||||
{
|
||||
strncpy(name, CONFIG_RAGILE_PRODUCT_NAME, len - 1);
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int firmware_check_file_is_dir(char *dir, char *file_name)
|
||||
{
|
||||
int ret;
|
||||
struct stat buf;
|
||||
char tmp[FIRMWARE_FILE_DIR_LEN];
|
||||
|
||||
if (strcmp(file_name, ".") == 0 || strcmp(file_name, "..") == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mem_clear(tmp, FIRMWARE_FILE_DIR_LEN);
|
||||
snprintf(tmp, FIRMWARE_FILE_DIR_LEN - 1, "%s/%s", dir, file_name);
|
||||
ret = stat(tmp, &buf);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (S_ISDIR(buf.st_mode)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int firmware_error_type(int action, name_info_t *info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
return ERR_FW_UPGRADE;
|
||||
}
|
||||
if (info->type == FIRMWARE_CPLD) {
|
||||
switch (action) {
|
||||
case FIRMWARE_ACTION_CHECK:
|
||||
return ERR_FW_CHECK_CPLD_UPGRADE;
|
||||
case FIRMWARE_ACTION_UPGRADE:
|
||||
return ERR_FW_DO_CPLD_UPGRADE;
|
||||
default:
|
||||
return ERR_FW_UPGRADE;
|
||||
}
|
||||
} else if (info->type == FIRMWARE_FPGA) {
|
||||
switch (action) {
|
||||
case FIRMWARE_ACTION_CHECK:
|
||||
return ERR_FW_CHECK_FPGA_UPGRADE;
|
||||
case FIRMWARE_ACTION_UPGRADE:
|
||||
return ERR_FW_DO_FPGA_UPGRADE;
|
||||
default:
|
||||
return ERR_FW_UPGRADE;
|
||||
}
|
||||
} else {
|
||||
return ERR_FW_UPGRADE;
|
||||
}
|
||||
}
|
||||
|
||||
/* analyze file's name,Name rule: card name_firmware type_slot number_firmware chip name.bin*/
|
||||
static int firmware_parse_file_name(char *name, name_info_t *info)
|
||||
{
|
||||
int i;
|
||||
char *tmp, *start;
|
||||
char slot[FIRMWARE_NAME_LEN];
|
||||
|
||||
dbg_print(is_debug_on, "Parse file name: %s\n", name);
|
||||
|
||||
start = name;
|
||||
/* card name */
|
||||
tmp = strchr(start, '_');
|
||||
if (tmp == NULL) {
|
||||
dbg_print(is_debug_on, "Failed to get card name form file name: %s.\n", name);
|
||||
return firmware_error_type(FIRMWARE_ACTION_CHECK, NULL);
|
||||
}
|
||||
|
||||
strncpy(info->card_name, start,
|
||||
(tmp - start > FIRMWARE_NAME_LEN - 1) ? (FIRMWARE_NAME_LEN - 1) : (tmp - start));
|
||||
|
||||
/* firmware type */
|
||||
start = tmp + 1;
|
||||
tmp = strchr(start, '_');
|
||||
if (tmp == NULL) {
|
||||
dbg_print(is_debug_on, "Failed to get upgrade type form file name: %s.\n", name);
|
||||
return firmware_error_type(FIRMWARE_ACTION_CHECK, NULL);
|
||||
}
|
||||
|
||||
if (strncmp(start, FIRMWARE_CPLD_NAME, tmp - start) == 0) {
|
||||
info->type = FIRMWARE_CPLD;
|
||||
} else if (strncmp(start, FIRMWARE_FPGA_NAME, tmp - start) == 0) {
|
||||
info->type = FIRMWARE_FPGA;
|
||||
} else {
|
||||
info->type = FIRMWARE_OTHER;
|
||||
}
|
||||
|
||||
/* slot number */
|
||||
start = tmp + 1;
|
||||
tmp = strchr(start, '_');
|
||||
if (tmp == NULL) {
|
||||
dbg_print(is_debug_on, "Failed to get slot form file name: %s.\n", name);
|
||||
return firmware_error_type(FIRMWARE_ACTION_CHECK, info);
|
||||
}
|
||||
|
||||
mem_clear(slot, FIRMWARE_NAME_LEN);
|
||||
strncpy(slot, start,
|
||||
((tmp - start > FIRMWARE_NAME_LEN - 1) ? FIRMWARE_NAME_LEN - 1 : tmp - start));
|
||||
|
||||
for (i = 0; i < FIRMWARE_NAME_LEN && slot[i] != '\0'; i++) {
|
||||
if (!isdigit(slot[i])) {
|
||||
return firmware_error_type(FIRMWARE_ACTION_CHECK, info);
|
||||
}
|
||||
}
|
||||
|
||||
dbg_print(is_debug_on, "get slot info: %s.\n", name);
|
||||
info->slot = strtoul(slot, NULL, 10);
|
||||
dbg_print(is_debug_on, "get slot info slot: %d.\n", info->slot);
|
||||
|
||||
/* firmware chip name */
|
||||
start = tmp + 1;
|
||||
tmp = strchr(start, '_');
|
||||
if (tmp == NULL) {
|
||||
dbg_print(is_debug_on, "Failed to get chip name form file name: %s.\n", name);
|
||||
return firmware_error_type(FIRMWARE_ACTION_CHECK, info);
|
||||
}
|
||||
strncpy(info->chip_name, start,
|
||||
(tmp - start > FIRMWARE_NAME_LEN - 1) ? (FIRMWARE_NAME_LEN - 1) : (tmp - start));
|
||||
|
||||
/* version */
|
||||
start = tmp + 1;
|
||||
tmp = strstr(start, ".vme");
|
||||
if (tmp == NULL) {
|
||||
dbg_print(is_debug_on, "Failed to get chip version form file name: %s.\n", name);
|
||||
return firmware_error_type(FIRMWARE_ACTION_CHECK, info);
|
||||
}
|
||||
strncpy(info->version, start,
|
||||
(tmp - start > FIRMWARE_NAME_LEN - 1) ? (FIRMWARE_NAME_LEN - 1) : (tmp - start));
|
||||
|
||||
/* finish checking */
|
||||
if (strcmp(tmp, ".vme") != 0) {
|
||||
dbg_print(is_debug_on, "The file format is wrong: %s.\n", name);
|
||||
return firmware_error_type(FIRMWARE_ACTION_CHECK, info);
|
||||
}
|
||||
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
/* check the file information to determine whether the file can be used in the device */
|
||||
static int firmware_check_file_info(name_info_t *info)
|
||||
{
|
||||
int ret;
|
||||
char card_name[FIRMWARE_NAME_LEN];
|
||||
|
||||
dbg_print(is_debug_on, "Check file info.\n");
|
||||
|
||||
/* get card name */
|
||||
mem_clear(card_name, FIRMWARE_NAME_LEN);
|
||||
ret = firmware_get_card_name(card_name, FIRMWARE_NAME_LEN);
|
||||
if (ret != FIRMWARE_SUCCESS) {
|
||||
dbg_print(is_debug_on, "Failed to get card name.(%s)\n", info->card_name);
|
||||
return firmware_error_type(FIRMWARE_ACTION_CHECK, info);
|
||||
}
|
||||
|
||||
/* check card name */
|
||||
dbg_print(is_debug_on, "The card name: %s, the file card name: %s.\n",
|
||||
card_name, info->card_name);
|
||||
if (strcmp(card_name, info->card_name) != 0) {
|
||||
dbg_print(is_debug_on, "The file card name %s is wrong.(real: %s)\n",
|
||||
info->card_name, card_name);
|
||||
return firmware_error_type(FIRMWARE_ACTION_CHECK, info);
|
||||
}
|
||||
|
||||
/* check type */
|
||||
if (info->type != FIRMWARE_CPLD && info->type != FIRMWARE_FPGA) {
|
||||
dbg_print(is_debug_on, "The file type %d is wrong.(cpld %d, fpga %d)\n",
|
||||
info->type, FIRMWARE_CPLD, FIRMWARE_FPGA);
|
||||
return firmware_error_type(FIRMWARE_ACTION_CHECK, info);
|
||||
}
|
||||
|
||||
/* check slot */
|
||||
if (info->slot < 1 || info->slot > FIRMWARE_MAX_SLOT_NUM) {
|
||||
dbg_print(is_debug_on, "The file slot %d is wrong.\n", info->slot);
|
||||
return firmware_error_type(FIRMWARE_ACTION_CHECK, info);
|
||||
}
|
||||
|
||||
dbg_print(is_debug_on, "Success check file info.\n");
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
static void firmware_get_dev_file_name(name_info_t *info, char *file_name, int len)
|
||||
{
|
||||
if (info->type == FIRMWARE_CPLD) {
|
||||
snprintf(file_name, len, "/dev/firmware_cpld_ispvme%d", info->slot - 1);
|
||||
} else if (info->type == FIRMWARE_FPGA) {
|
||||
snprintf(file_name, len, "/dev/firmware_fpga_ispvme%d", info->slot - 1);
|
||||
} else {
|
||||
snprintf(file_name, len, "/dev/firmware_ispvme%d", info->slot - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void firmware_set_driver_debug(int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (is_debug_on == DEBUG_ALL_ON || is_debug_on == DEBUG_KERN_ON) {
|
||||
ret = ioctl(fd, FIRMWARE_SET_DEBUG_ON, NULL);
|
||||
if (ret < 0) {
|
||||
dbg_print(is_debug_on, "Failed to set driver debug on.\n");
|
||||
} else {
|
||||
dbg_print(is_debug_on, "Open driver debug.\n");
|
||||
}
|
||||
} else if (is_debug_on == DEBUG_OFF) {
|
||||
ret = ioctl(fd, FIRMWARE_SET_DEBUG_OFF, NULL);
|
||||
if (ret < 0) {
|
||||
dbg_print(is_debug_on, "Failed to set driver debug off.\n");
|
||||
} else {
|
||||
dbg_print(is_debug_on, "OFF driver debug.\n");
|
||||
}
|
||||
} else {
|
||||
dbg_print(is_debug_on, "Ignore driver debug.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int firmware_check_chip_name(int fd, name_info_t *info)
|
||||
{
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
static int firmware_check_chip_verison(int fd, name_info_t *info)
|
||||
{
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
static int firmware_get_file_size(char *file_name, int *size)
|
||||
{
|
||||
int ret;
|
||||
struct stat buf;
|
||||
|
||||
ret = stat(file_name, &buf);
|
||||
if (ret < 0) {
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
if (buf.st_size < 0) {
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
*size = buf.st_size;
|
||||
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
static int firmware_get_file_info(char *file_name, char *buf, int size)
|
||||
{
|
||||
FILE *fp;
|
||||
int len;
|
||||
|
||||
fp = fopen(file_name, "r");
|
||||
if (fp == NULL) {
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
len = fread(buf, size, 1, fp);
|
||||
if (len < 0) {
|
||||
fclose(fp);
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
static int firmware_upgrade_info(int fd, char *buf, int size)
|
||||
{
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
/* upgrade CPLD */
|
||||
static int firmware_upgrade(char *dir, char *file_name, name_info_t *info)
|
||||
{
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
static int firmware_upgrade_file(char *dir, char *file_name)
|
||||
{
|
||||
int ret, argc;
|
||||
name_info_t info;
|
||||
char *argv[2];
|
||||
char tmp_file[FIRMWARE_FILE_DIR_LEN];
|
||||
|
||||
mem_clear(&info, sizeof(name_info_t));
|
||||
ret = firmware_parse_file_name(file_name, &info);
|
||||
if (ret != FIRMWARE_SUCCESS) {
|
||||
dbg_print(is_debug_on, "Failed to parse file name: %s\n", file_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dbg_print(is_debug_on, "The file name parse:(%s) \n"
|
||||
" card name: %s, \n"
|
||||
" type : %d, \n"
|
||||
" slot : %d, \n"
|
||||
" chip name: %s \n"
|
||||
" version : %s \n",
|
||||
file_name, info.card_name, info.type, info.slot, info.chip_name, info.version);
|
||||
|
||||
ret = firmware_check_file_info(&info);
|
||||
if (ret != FIRMWARE_SUCCESS) {
|
||||
dbg_print(is_debug_on, "Failed to check file name: %s\n", file_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get the information of upgrade file */
|
||||
mem_clear(tmp_file, FIRMWARE_FILE_DIR_LEN);
|
||||
if (dir != NULL) {
|
||||
snprintf(tmp_file, FIRMWARE_FILE_DIR_LEN - 1, "%s/%s", dir, file_name);
|
||||
} else {
|
||||
snprintf(tmp_file, FIRMWARE_FILE_DIR_LEN - 1, "%s", file_name);
|
||||
}
|
||||
|
||||
argc = 2;
|
||||
argv[1] = tmp_file;
|
||||
ret = ispvme_main(argc, (char **)&argv);
|
||||
if (ret != FIRMWARE_SUCCESS){
|
||||
dbg_print(is_debug_on, "Failed to upgrade file name: %s\n", file_name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int firmware_upgrade_set_gpio_info(int slot)
|
||||
{
|
||||
firmware_card_info_t *hw_info;
|
||||
cmd_info_t cmd_info;
|
||||
firmware_upg_gpio_info_t *gpio_info;
|
||||
int ret;
|
||||
int fd;
|
||||
int dev_type;
|
||||
int my_slot;
|
||||
|
||||
ret = 0;
|
||||
|
||||
dev_type = drv_get_my_dev_type();
|
||||
fd = open("/dev/firmware_cpld_ispvme0", O_RDWR);
|
||||
if (fd < 0) {
|
||||
dbg_print(is_debug_on, "%s can't open device\r\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hw_info = firmware_get_card_info(dev_type);
|
||||
|
||||
if (hw_info == NULL) {
|
||||
dbg_print(is_debug_on, "card type 0x%x don't support firmware.\n", dev_type);
|
||||
ret = -1;
|
||||
goto gpio_info_err;
|
||||
}
|
||||
|
||||
if (slot >= hw_info->slot_num) {
|
||||
dbg_print(is_debug_on, "slot %d is too large, support slot num %d.\n", slot, hw_info->slot_num);
|
||||
ret = -1;
|
||||
goto gpio_info_err;
|
||||
}
|
||||
|
||||
gpio_info = &(hw_info->gpio_info[slot]);
|
||||
cmd_info.size = sizeof(firmware_upg_gpio_info_t);
|
||||
cmd_info.data = (void *)gpio_info;
|
||||
|
||||
dbg_print(is_debug_on, "slot = %d, gpio_info[jtag_en:%d select:%d tck:%d tdi:%d tdo=%d tms=%d]\n",slot, \
|
||||
gpio_info->jtag_en, gpio_info->select,gpio_info->tck,gpio_info->tdi,gpio_info->tdo,gpio_info->tms);
|
||||
|
||||
ret = ioctl(fd, FIRMWARE_SET_GPIO_INFO, &cmd_info);
|
||||
|
||||
gpio_info_err:
|
||||
if (ret < 0) {
|
||||
dbg_print(is_debug_on, "Failed due to:set gpio info.\n");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* argv[1]: file name
|
||||
* argv[2]: type
|
||||
* argv[3]: slot number
|
||||
* argv[4]: chip name
|
||||
*/
|
||||
static int firmware_upgrade_one_file(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
name_info_t info;
|
||||
char tmp[FIRMWARE_FILE_DIR_LEN];
|
||||
|
||||
mem_clear(&info, sizeof(name_info_t));
|
||||
|
||||
info.slot = strtoul(argv[3], NULL, 10);
|
||||
strncpy(info.chip_name, argv[4], FIRMWARE_NAME_LEN - 1);
|
||||
|
||||
if (strcmp(argv[2], FIRMWARE_CPLD_NAME) == 0) { /* CPLD upgrade */
|
||||
if(is_vme_file(argv[1]) == 1){ /* VME upgrade file */
|
||||
dbg_print(is_debug_on, "vme file\n");
|
||||
info.type = FIRMWARE_CPLD;
|
||||
ret = firmware_upgrade_set_gpio_info(info.slot);
|
||||
if (ret < 0) {
|
||||
goto upgrade_err;
|
||||
}
|
||||
ret = ispvme_main(2, argv);
|
||||
}
|
||||
else if(is_vme_file(argv[1]) == 0){ /* bin upgrade file */
|
||||
dbg_print(is_debug_on, "bin file\n");
|
||||
mem_clear(tmp, FIRMWARE_FILE_DIR_LEN);
|
||||
snprintf(tmp, FIRMWARE_FILE_DIR_LEN, "firmware_upgrade_bin %s %s %s %s", argv[1], argv[2], argv[3], argv[4]);
|
||||
ret = system(tmp);
|
||||
}
|
||||
else{
|
||||
dbg_print(is_debug_on, "unknow file\n");
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[2], FIRMWARE_FPGA_NAME) == 0) { /* FPGA upgrade */
|
||||
info.type = FIRMWARE_FPGA;
|
||||
ret = dfd_fpga_upgrade_do_upgrade(argv[1]);
|
||||
} else {
|
||||
dbg_print(is_debug_on, "Failed to get upgrade type: %s.\n", argv[2]);
|
||||
return ERR_FW_UPGRADE;
|
||||
}
|
||||
|
||||
upgrade_err:
|
||||
if (ret != FIRMWARE_SUCCESS){
|
||||
dbg_print(is_debug_on, "Failed to upgrade: %s.\n", argv[1]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void firmware_get_err_type(int err, int *real_err)
|
||||
{
|
||||
int tmp_err;
|
||||
|
||||
tmp_err = *real_err;
|
||||
|
||||
if (tmp_err == err) {
|
||||
return;
|
||||
}
|
||||
switch (err) {
|
||||
case ERR_FW_DO_CPLD_UPGRADE:
|
||||
case ERR_FW_DO_FPGA_UPGRADE:
|
||||
if (tmp_err == ERR_FW_CHECK_CPLD_UPGRADE
|
||||
|| tmp_err == ERR_FW_CHECK_FPGA_UPGRADE
|
||||
|| tmp_err == FIRMWARE_SUCCESS || tmp_err == ERR_FW_UPGRADE) {
|
||||
tmp_err = err;
|
||||
}
|
||||
break;
|
||||
case ERR_FW_CHECK_CPLD_UPGRADE:
|
||||
case ERR_FW_CHECK_FPGA_UPGRADE:
|
||||
if (tmp_err == FIRMWARE_SUCCESS || tmp_err == ERR_FW_UPGRADE) {
|
||||
tmp_err = err;
|
||||
}
|
||||
break;
|
||||
case ERR_FW_UPGRADE:
|
||||
if (tmp_err == FIRMWARE_SUCCESS) {
|
||||
tmp_err = err;
|
||||
}
|
||||
break;
|
||||
case FIRMWARE_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
*real_err = tmp_err;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* argv[1]: Pathname */
|
||||
static int firmware_upgrade_one_dir(int argc, char *argv[])
|
||||
{
|
||||
int ret, real_ret;
|
||||
int flag;
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
char *dir;
|
||||
|
||||
dir = argv[1];
|
||||
dirp = opendir(dir);
|
||||
if (dirp == NULL) {
|
||||
dbg_print(is_debug_on, "Failed to open the dir: %s.\n", dir);
|
||||
return ERR_FW_UPGRADE;
|
||||
}
|
||||
|
||||
ret = ERR_FW_UPGRADE;
|
||||
real_ret = FIRMWARE_SUCCESS;
|
||||
flag = 0;
|
||||
for (;;) {
|
||||
/* read the pathname of the file */
|
||||
dp = readdir(dirp);
|
||||
if (dp == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
dbg_print(is_debug_on, "The file name: %s.\n", dp->d_name);
|
||||
/* check whether it is a file */
|
||||
if (firmware_check_file_is_dir(dir, dp->d_name) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dbg_print(is_debug_on, "\n=========== Start: %s ===========\n", dp->d_name);
|
||||
|
||||
/* upgrade a upgrade file */
|
||||
ret = firmware_upgrade_file(dir, dp->d_name);
|
||||
if (ret != FIRMWARE_SUCCESS) {
|
||||
firmware_get_err_type(ret, &real_ret);
|
||||
dbg_print(is_debug_on, "Failed to upgrade the file: %s.(%d, %d)\n", dp->d_name, ret, real_ret);
|
||||
} else {
|
||||
flag = 1;
|
||||
dbg_print(is_debug_on, "Upgrade the file: %s success.\n", dp->d_name);
|
||||
}
|
||||
|
||||
dbg_print(is_debug_on, "=========== End: %s ===========\n", dp->d_name);
|
||||
}
|
||||
|
||||
if (flag == 1 && (real_ret == ERR_FW_CHECK_CPLD_UPGRADE || real_ret == ERR_FW_CHECK_FPGA_UPGRADE)) {
|
||||
real_ret = FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
if (real_ret != FIRMWARE_SUCCESS) {
|
||||
dbg_print(is_debug_on, "Failed to upgrade: %s.\n", dir);
|
||||
} else {
|
||||
dbg_print(is_debug_on, "Upgrade success: %s.\n", dir);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
return real_ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* argv[1]: file name
|
||||
* argv[2]: type
|
||||
* argv[3]: slot number
|
||||
*/
|
||||
static int firmware_upgrade_read_chip(int argc, char *argv[])
|
||||
{
|
||||
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
static int firmware_upgrade_test_fpga(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
char tmp1[128];
|
||||
char tmp2[128];
|
||||
|
||||
if ((strcmp(argv[1], FIRMWARE_FPGA_NAME) != 0)
|
||||
|| (strcmp(argv[2], FIRMWARE_FPGA_TEST) != 0)) {
|
||||
snprintf(tmp1, sizeof(tmp1), "%s", argv[1]);
|
||||
snprintf(tmp2, sizeof(tmp2), "%s", argv[2]);
|
||||
printf( "fpga test:Failed to Input ERR Parm, argv[1]:%s, agrv[2]:%s\n", tmp1,tmp2);
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
ret = dfd_fpga_upgrade_test();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int firmware_upgrade_test_chip(int argc, char *argv[])
|
||||
{
|
||||
int ret,dev_type,slot;
|
||||
int err_ret=0;
|
||||
firmware_card_info_t *hw_info;
|
||||
char tmp1[128];
|
||||
char tmp2[128];
|
||||
|
||||
if ((strcmp(argv[1], FIRMWARE_CPLD_NAME) != 0)
|
||||
|| (strcmp(argv[2], FIRMWARE_CPLD_TEST) != 0)) {
|
||||
snprintf(tmp1, sizeof(tmp1), "%s", argv[1]);
|
||||
snprintf(tmp2, sizeof(tmp2), "%s", argv[2]);
|
||||
printf( "gpio test:Failed to Input ERR Parm, argv[1]:%s, agrv[2]:%s\n", tmp1, tmp2);
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
dev_type = drv_get_my_dev_type(); /* get the type of card first */
|
||||
if (dev_type < 0) {
|
||||
printf("gpio test:drv_get_my_dev_type failed ret 0x%x.\n", dev_type);
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
hw_info = firmware_get_card_info(dev_type); /* get the detail information of card */
|
||||
if (hw_info == NULL) {
|
||||
printf( "gpio test:card type 0x%x don't support firmware.\n", dev_type);
|
||||
return FIRMWARE_FAILED;
|
||||
}
|
||||
|
||||
for(slot = 0; slot < hw_info->slot_num; slot++){
|
||||
ret = firmware_upgrade_set_gpio_info(slot); /* set GPIO information */
|
||||
if(ret < 0){
|
||||
err_ret++;
|
||||
printf( "gpio test:Failed to set gpio info,dev_type 0x%x,slot %d\n", dev_type, slot);
|
||||
continue;
|
||||
}
|
||||
ret = ispvme_test(); /* GPIO path test */
|
||||
if(ret != 0){
|
||||
err_ret++;
|
||||
printf("gpio test:ispvme_test failed,dev_type 0x%x,slot %d\n", dev_type, slot);
|
||||
}
|
||||
}
|
||||
if(err_ret != 0)
|
||||
return FIRMWARE_FAILED;
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
is_debug_on = firmware_upgrade_debug();
|
||||
|
||||
if (argc != 2 && argc != 5 && argc != 4 && argc != 3 && argc != 6) {
|
||||
printf("Use:\n");
|
||||
printf(" upgrade dir : firmware_upgrade_ispvme dir\n");
|
||||
printf(" upgrade file : firmware_upgrade_ispvme file type slot chip_name\n");
|
||||
printf(" read chip : firmware_upgrade_ispvme file type slot\n");
|
||||
dbg_print(is_debug_on, "Failed to upgrade the number of argv: %d.\n", argc);
|
||||
return ERR_FW_UPGRADE;
|
||||
}
|
||||
#if 0
|
||||
ret = dev_drv_init();
|
||||
if (ret) {
|
||||
dbg_print(is_debug_on, "failed to init dfd ret %d.", ret);
|
||||
return ERR_FW_UPGRADE;
|
||||
}
|
||||
#endif
|
||||
/* dump fpga flash operation */
|
||||
if (argc == 6) {
|
||||
if (strcmp(argv[1], "fpga_dump_flash") == 0) {
|
||||
ret = dfd_fpga_upgrade_dump_flash(argc, argv);
|
||||
printf("fpga_dump_flash ret %d.\n", ret);
|
||||
return FIRMWARE_SUCCESS;
|
||||
} else {
|
||||
printf("Not support, please check your cmd.\n");
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* upgrade individual files */
|
||||
if (argc == 5) {
|
||||
printf("+================================+\n");
|
||||
printf("|Begin to upgrade, please wait...|\n");
|
||||
ret = firmware_upgrade_one_file(argc, argv);
|
||||
if (ret != FIRMWARE_SUCCESS) {
|
||||
if(strcmp(argv[2], FIRMWARE_CPLD_NAME) == 0)
|
||||
printf("| CPLD Upgrade failed! |\n");
|
||||
else if(strcmp(argv[2], FIRMWARE_FPGA_NAME) == 0)
|
||||
printf("| FPGA Upgrade failed! |\n");
|
||||
else
|
||||
printf("| Failed to get upgrade type! |\n");
|
||||
printf("+================================+\n");
|
||||
dbg_print(is_debug_on, "Failed to upgrade a firmware file: %s.\n", argv[1]);
|
||||
return ret;
|
||||
}
|
||||
if(strcmp(argv[2], FIRMWARE_CPLD_NAME) == 0)
|
||||
printf("| CPLD Upgrade succeeded! |\n");
|
||||
else
|
||||
printf("| FPGA Upgrade succeeded! |\n");
|
||||
printf("+================================+\n");
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
printf("+================================+\n");
|
||||
printf("|Begin to upgrade, please wait...|\n");
|
||||
|
||||
ret = firmware_upgrade_one_dir(argc, argv);
|
||||
if (ret != FIRMWARE_SUCCESS) {
|
||||
printf("| Upgrade failed! |\n");
|
||||
printf("+================================+\n");
|
||||
dbg_print(is_debug_on, "Failed to upgrade a firmware dir: %s.\n", argv[1]);
|
||||
return ret;
|
||||
}
|
||||
printf("| Upgrade succeeded! |\n");
|
||||
printf("+================================+\n");
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
if (argc == 4) {
|
||||
ret = firmware_upgrade_read_chip(argc, argv);
|
||||
if (ret != FIRMWARE_SUCCESS) {
|
||||
dbg_print(is_debug_on, "Failed to read chip: %s.\n", argv[1]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
|
||||
if (argc == 3) {
|
||||
if (strcmp(argv[1], FIRMWARE_FPGA_NAME) == 0) {
|
||||
ret = firmware_upgrade_test_fpga(argc, argv);
|
||||
if (ret != FIRMWARE_SUCCESS) {
|
||||
printf("+=================+\n");
|
||||
printf("| FPGA TEST FAIL! |\n");
|
||||
printf("+=================+\n");
|
||||
return FIRMWARE_FAILED;
|
||||
} else {
|
||||
printf("+=================+\n");
|
||||
printf("| FPGA TEST PASS! |\n");
|
||||
printf("+=================+\n");
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = firmware_upgrade_test_chip(argc, argv);
|
||||
if (ret != FIRMWARE_SUCCESS) {
|
||||
printf("+=================+\n");
|
||||
printf("| GPIO TEST FAIL! |\n");
|
||||
printf("+=================+\n");
|
||||
return FIRMWARE_FAILED;
|
||||
} else {
|
||||
printf("+=================+\n");
|
||||
printf("| GPIO TEST PASS! |\n");
|
||||
printf("+=================+\n");
|
||||
return FIRMWARE_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_FW_UPGRADE;
|
||||
}
|
@ -1,249 +0,0 @@
|
||||
/*********************************************************************************
|
||||
* Lattice Semiconductor Corp. Copyright 2000-2008
|
||||
*
|
||||
* This is the hardware.c of ispVME V12.1 for JTAG programmable devices.
|
||||
* All the functions requiring customization are organized into this file for
|
||||
* the convinience of porting.
|
||||
*********************************************************************************/
|
||||
/*********************************************************************************
|
||||
* Revision History:
|
||||
*
|
||||
* 09/11/07 NN Type cast mismatch variables
|
||||
* 09/24/07 NN Added calibration function.
|
||||
* Calibration will help to determine the system clock frequency
|
||||
* and the count value for one micro-second delay of the target
|
||||
* specific hardware.
|
||||
* Modified the ispVMDelay function
|
||||
* Removed Delay Percent support
|
||||
* Moved the sclock() function from ivm_core.c to hardware.c
|
||||
*********************************************************************************/
|
||||
|
||||
/* #include <conio.h> */
|
||||
#include <stdint.h>
|
||||
#include <linux/types.h>
|
||||
#include "common.h"
|
||||
|
||||
/********************************************************************************
|
||||
* Declaration of global variables
|
||||
*
|
||||
*********************************************************************************/
|
||||
|
||||
unsigned char g_siIspPins = 0x00; /*Keeper of JTAG pin state*/
|
||||
unsigned short g_usInPort = 0x379; /*Address of the TDO pin*/
|
||||
unsigned short g_usOutPort = 0x378; /*Address of TDI, TMS, TCK pin*/
|
||||
unsigned short g_usCpu_Frequency = 1000; /*Enter your CPU frequency here, unit in MHz.*/
|
||||
|
||||
/*********************************************************************************
|
||||
* This is the definition of the bit locations of each respective
|
||||
* signal in the global variable g_siIspPins.
|
||||
*
|
||||
* NOTE: Users must add their own implementation here to define
|
||||
* the bit location of the signal to target their hardware.
|
||||
* The example below is for the Lattice download cable on
|
||||
* on the parallel port.
|
||||
*
|
||||
*********************************************************************************/
|
||||
|
||||
#if 0
|
||||
const unsigned char g_ucPinTDI = JTAG_TDI; /* Bit address of TDI */
|
||||
const unsigned char g_ucPinTCK = JTAG_TCK; /* Bit address of TCK */
|
||||
const unsigned char g_ucPinTMS = JTAG_TMS; /* Bit address of TMS */
|
||||
const unsigned char g_ucPinENABLE = JTAG_ENABLE; /* Bit address of ENABLE */
|
||||
const unsigned char g_ucPinTRST = JTAG_TRST; /* Bit address of TRST */
|
||||
const unsigned char g_ucPinTDO = JTAG_TDO; /* Bit address of TDO*/
|
||||
#endif
|
||||
int g_file_fd;
|
||||
/***************************************************************
|
||||
*
|
||||
* Functions declared in hardware.c module.
|
||||
*
|
||||
***************************************************************/
|
||||
void writePort(unsigned char a_ucPins, unsigned char a_ucValue);
|
||||
unsigned char readPort();
|
||||
void sclock();
|
||||
void ispVMDelay(unsigned short a_usTimeDelay);
|
||||
void calibration(void);
|
||||
|
||||
/********************************************************************************
|
||||
* writePort
|
||||
* To apply the specified value to the pins indicated. This routine will
|
||||
* be modified for specific systems.
|
||||
* As an example, this code uses the IBM-PC standard Parallel port, along with the
|
||||
* schematic shown in Lattice documentation, to apply the signals to the
|
||||
* JTAG pins.
|
||||
*
|
||||
* PC Parallel port pin Signal name Port bit address
|
||||
* 2 g_ucPinTDI 1
|
||||
* 3 g_ucPinTCK 2
|
||||
* 4 g_ucPinTMS 4
|
||||
* 5 g_ucPinENABLE 8
|
||||
* 6 g_ucPinTRST 16
|
||||
* 10 g_ucPinTDO 64
|
||||
*
|
||||
* Parameters:
|
||||
* - a_ucPins, which is actually a set of bit flags (defined above)
|
||||
* that correspond to the bits of the data port. Each of the I/O port
|
||||
* bits that drives an isp programming pin is assigned a flag
|
||||
* (through a #define) corresponding to the signal it drives. To
|
||||
* change the value of more than one pin at once, the flags are added
|
||||
* together, much like file access flags are.
|
||||
*
|
||||
* The bit flags are only set if the pin is to be changed. Bits that
|
||||
* do not have their flags set do not have their levels changed. The
|
||||
* state of the port is always manintained in the static global
|
||||
* variable g_siIspPins, so that each pin can be addressed individually
|
||||
* without disturbing the others.
|
||||
*
|
||||
* - a_ucValue, which is either HIGH (0x01 ) or LOW (0x00 ). Only these two
|
||||
* values are valid. Any non-zero number sets the pin(s) high.
|
||||
*
|
||||
*********************************************************************************/
|
||||
|
||||
void writePort(unsigned char a_ucPins, unsigned char a_ucValue)
|
||||
{
|
||||
switch (a_ucPins) {
|
||||
case JTAG_TCK:
|
||||
ioctl(g_file_fd, FIRMWARE_JTAG_TCK, &a_ucValue);
|
||||
break;
|
||||
case JTAG_TDI:
|
||||
ioctl(g_file_fd, FIRMWARE_JTAG_TDI, &a_ucValue);
|
||||
break;
|
||||
case JTAG_TMS:
|
||||
ioctl(g_file_fd, FIRMWARE_JTAG_TMS, &a_ucValue);
|
||||
break;
|
||||
case JTAG_ENABLE:
|
||||
ioctl(g_file_fd, FIRMWARE_JTAG_EN, &a_ucValue);
|
||||
break;
|
||||
case JTAG_TRST:
|
||||
/* ioctl(g_file_fd, FIRMWARE_JTAG_TRST, &a_ucValue); */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
*
|
||||
* readPort
|
||||
*
|
||||
* Returns the value of the TDO from the device.
|
||||
*
|
||||
**********************************************************************************/
|
||||
unsigned char readPort()
|
||||
{
|
||||
unsigned char ucRet = 0;
|
||||
|
||||
ioctl(g_file_fd, FIRMWARE_JTAG_TDO, &ucRet);
|
||||
return (ucRet);
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
* sclock
|
||||
*
|
||||
* Apply a pulse to TCK.
|
||||
*
|
||||
* This function is located here so that users can modify to slow down TCK if
|
||||
* it is too fast (> 25MHZ). Users can change the IdleTime assignment from 0 to
|
||||
* 1, 2... to effectively slowing down TCK by half, quarter...
|
||||
*
|
||||
*********************************************************************************/
|
||||
void sclock()
|
||||
{
|
||||
unsigned short IdleTime = 0; /* change to > 0 if need to slow down TCK */
|
||||
unsigned short usIdleIndex = 0;
|
||||
IdleTime++;
|
||||
for (usIdleIndex = 0; usIdleIndex < IdleTime; usIdleIndex++) {
|
||||
writePort(JTAG_TCK, 0x01);
|
||||
}
|
||||
for (usIdleIndex = 0; usIdleIndex < IdleTime; usIdleIndex++) {
|
||||
writePort(JTAG_TCK, 0x00);
|
||||
}
|
||||
}
|
||||
/********************************************************************************
|
||||
*
|
||||
* ispVMDelay
|
||||
*
|
||||
*
|
||||
* Users must implement a delay to observe a_usTimeDelay, where
|
||||
* bit 15 of the a_usTimeDelay defines the unit.
|
||||
* 1 = milliseconds
|
||||
* 0 = microseconds
|
||||
* Example:
|
||||
* a_usTimeDelay = 0x0001 = 1 microsecond delay.
|
||||
* a_usTimeDelay = 0x8001 = 1 millisecond delay.
|
||||
*
|
||||
* This subroutine is called upon to provide a delay from 1 millisecond to a few
|
||||
* hundreds milliseconds each time.
|
||||
* It is understood that due to a_usTimeDelay is defined as unsigned short, a 16 bits
|
||||
* integer, this function is restricted to produce a delay to 64000 micro-seconds
|
||||
* or 32000 milli-second maximum. The VME file will never pass on to this function
|
||||
* a delay time > those maximum number. If it needs more than those maximum, the VME
|
||||
* file will launch the delay function several times to realize a larger delay time
|
||||
* cummulatively.
|
||||
* It is perfectly alright to provide a longer delay than required. It is not
|
||||
* acceptable if the delay is shorter.
|
||||
*
|
||||
* Delay function example--using the machine clock signal of the native CPU------
|
||||
* When porting ispVME to a native CPU environment, the speed of CPU or
|
||||
* the system clock that drives the CPU is usually known.
|
||||
* The speed or the time it takes for the native CPU to execute one for loop
|
||||
* then can be calculated as follows:
|
||||
* The for loop usually is compiled into the ASSEMBLY code as shown below:
|
||||
* LOOP: DEC RA;
|
||||
* JNZ LOOP;
|
||||
* If each line of assembly code needs 4 machine cycles to execute,
|
||||
* the total number of machine cycles to execute the loop is 2 x 4 = 8.
|
||||
* Usually system clock = machine clock (the internal CPU clock).
|
||||
* Note: Some CPU has a clock multiplier to double the system clock for
|
||||
the machine clock.
|
||||
*
|
||||
* Let the machine clock frequency of the CPU be F, or 1 machine cycle = 1/F.
|
||||
* The time it takes to execute one for loop = (1/F ) x 8.
|
||||
* Or one micro-second = F(MHz)/8;
|
||||
*
|
||||
* Example: The CPU internal clock is set to 100Mhz, then one micro-second = 100/8 = 12
|
||||
*
|
||||
* The C code shown below can be used to create the milli-second accuracy.
|
||||
* Users only need to enter the speed of the cpu.
|
||||
*
|
||||
**********************************************************************************/
|
||||
void ispVMDelay(unsigned short a_usTimeDelay)
|
||||
{
|
||||
if (a_usTimeDelay & 0x8000) {
|
||||
a_usTimeDelay &= ~0x8000; /* change it to ms */
|
||||
usleep(a_usTimeDelay * 1000); /* Use usleep to improve accuracy */
|
||||
} else
|
||||
usleep(a_usTimeDelay);
|
||||
return;
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
*
|
||||
* calibration
|
||||
*
|
||||
* It is important to confirm if the delay function is indeed providing
|
||||
* the accuracy required. Also one other important parameter needed
|
||||
* checking is the clock frequency.
|
||||
* Calibration will help to determine the system clock frequency
|
||||
* and the loop_per_micro value for one micro-second delay of the target
|
||||
* specific hardware.
|
||||
*
|
||||
**********************************************************************************/
|
||||
void calibration(void)
|
||||
{
|
||||
/*Apply 2 pulses to TCK.*/
|
||||
writePort(JTAG_TCK, 0x00);
|
||||
writePort(JTAG_TCK, 0x01);
|
||||
writePort(JTAG_TCK, 0x00);
|
||||
writePort(JTAG_TCK, 0x01);
|
||||
writePort(JTAG_TCK, 0x00);
|
||||
|
||||
/*Delay for 1 millisecond. Pass on 1000 or 0x8001 both = 1ms delay.*/
|
||||
ispVMDelay(0x8001);
|
||||
|
||||
/*Apply 2 pulses to TCK*/
|
||||
writePort(JTAG_TCK, 0x01);
|
||||
writePort(JTAG_TCK, 0x00);
|
||||
writePort(JTAG_TCK, 0x01);
|
||||
writePort(JTAG_TCK, 0x00);
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
#ifndef __FIRMWARE_UPGRADE_DEBUG_H__
|
||||
#define __FIRMWARE_UPGRADE_DEBUG_H__
|
||||
|
||||
#define DEBUG_INFO_LEN 20
|
||||
#define DEBUG_FILE "/.firmware_upgrade_debug"
|
||||
#define DEBUG_ON_ALL "3"
|
||||
#define DEBUG_ON_KERN "2"
|
||||
#define DEBUG_ON_INFO "1"
|
||||
#define DEBUG_OFF_INFO "0"
|
||||
|
||||
enum debug_s {
|
||||
DEBUG_OFF = 0, /* debug off */
|
||||
DEBUG_APP_ON, /* debug app on */
|
||||
DEBUG_KERN_ON, /* kernel debug on */
|
||||
DEBUG_ALL_ON, /* debug app and kernel debug on */
|
||||
DEBUG_IGNORE, /* ignore debug */
|
||||
};
|
||||
|
||||
extern int firmware_upgrade_debug(void);
|
||||
|
||||
#endif /* End of __FIRMWARE_UPGRADE_DEBUG_H__ */
|
@ -1,119 +0,0 @@
|
||||
#ifndef __FIRMWARE_APP_H__
|
||||
#define __FIRMWARE_APP_H__
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <debug_ispvme.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Agreement with PKG_MGMT module */
|
||||
#define ERR_FW_CHECK_CPLD_UPGRADE (440 - 256)
|
||||
#define ERR_FW_CHECK_FPGA_UPGRADE (441 - 256)
|
||||
#define ERR_FW_DO_CPLD_UPGRADE (442 - 256)
|
||||
#define ERR_FW_DO_FPGA_UPGRADE (443 - 256)
|
||||
#define ERR_FW_UPGRADE (444 - 256)
|
||||
|
||||
#define FIRMWARE_FAILED -1
|
||||
#define FIRMWARE_SUCCESS 0
|
||||
|
||||
#define FIRMWARE_ACTION_CHECK 0
|
||||
#define FIRMWARE_ACTION_UPGRADE 1
|
||||
|
||||
#define mem_clear(data, size) memset((data), 0, (size))
|
||||
|
||||
#define dbg_print(debug, fmt, arg...) \
|
||||
if (debug == DEBUG_APP_ON || debug == DEBUG_ALL_ON) \
|
||||
{ do{printf(fmt,##arg);} while(0); }
|
||||
|
||||
#define FIRMWARE_FILE_DIR_LEN 128
|
||||
#define FIRMWARE_NAME_LEN 48
|
||||
#define FIRMWARE_MAX_SLOT_NUM 32
|
||||
|
||||
#define FIRMWARE_CPLD_NAME "cpld"
|
||||
#define FIRMWARE_FPGA_NAME "fpga"
|
||||
|
||||
#define FIRMWARE_CPLD_EPM1270F256 "EPM1270F256"
|
||||
#define FIRMWARE_CPLD_5M1270 "5M1270"
|
||||
#define FIRMWARE_CPLD_TEST "test"
|
||||
#define FIRMWARE_FPGA_TEST "test"
|
||||
|
||||
/* ioctl command */
|
||||
#define FIRMWARE_TYPE 'F'
|
||||
|
||||
#define FIRMWARE_JTAG_TDI _IOR(FIRMWARE_TYPE, 0, char)
|
||||
#define FIRMWARE_JTAG_TDO _IOR(FIRMWARE_TYPE, 1, char)
|
||||
#define FIRMWARE_JTAG_TCK _IOR(FIRMWARE_TYPE, 2, char)
|
||||
#define FIRMWARE_JTAG_TMS _IOR(FIRMWARE_TYPE, 3, char)
|
||||
#define FIRMWARE_JTAG_EN _IOR(FIRMWARE_TYPE, 4, char)
|
||||
#define FIRMWARE_SET_DEBUG_ON _IOW(FIRMWARE_TYPE, 5, int) /* debug on */
|
||||
#define FIRMWARE_SET_DEBUG_OFF _IOW(FIRMWARE_TYPE, 6, int) /* debug off */
|
||||
#define FIRMWARE_SET_GPIO_INFO _IOR(FIRMWARE_TYPE, 7, int) /* GPIO info */
|
||||
|
||||
#define FIRMWARE_MAX_SUB_SLOT_NUM (8)
|
||||
#define FIRMWARE_MAX_CARD_SLOT_NUM ((FIRMWARE_MAX_SUB_SLOT_NUM) + (1))/* max slot num */
|
||||
#define FIRMWARE_CARD_NAME_MAX_LEN (64)
|
||||
#define GPIO(p, v, d) { \
|
||||
.pin = p, \
|
||||
.val = v, \
|
||||
.dir = d, \
|
||||
},
|
||||
|
||||
enum firmware_type_s {
|
||||
FIRMWARE_CPLD = 0,
|
||||
FIRMWARE_FPGA,
|
||||
FIRMWARE_OTHER,
|
||||
};
|
||||
|
||||
typedef struct name_info_s {
|
||||
char card_name[FIRMWARE_NAME_LEN]; /* card name */
|
||||
int type; /* upgrade file type */
|
||||
int slot; /* slot number correspoding to upgrade file */
|
||||
char chip_name[FIRMWARE_NAME_LEN]; /* chip name */
|
||||
char version[FIRMWARE_NAME_LEN]; /* version */
|
||||
} name_info_t;
|
||||
|
||||
typedef struct cmd_info_s {
|
||||
int size;
|
||||
void *data;
|
||||
} cmd_info_t;
|
||||
|
||||
typedef struct gpio_group_s {
|
||||
int pin;
|
||||
int val;
|
||||
int dir;
|
||||
} gpio_group_t;
|
||||
|
||||
typedef struct firmware_upg_gpio_info_s {
|
||||
int tdi;
|
||||
int tck;
|
||||
int tms;
|
||||
int tdo;
|
||||
int jtag_en;
|
||||
int select;
|
||||
gpio_group_t jtag_5;
|
||||
gpio_group_t jtag_4;
|
||||
gpio_group_t jtag_3;
|
||||
gpio_group_t jtag_2;
|
||||
gpio_group_t jtag_1;
|
||||
} firmware_upg_gpio_info_t;
|
||||
|
||||
typedef struct firmware_card_info_s {
|
||||
int dev_type; /* the type of card */
|
||||
int slot_num;
|
||||
char card_name[FIRMWARE_CARD_NAME_MAX_LEN];
|
||||
firmware_upg_gpio_info_t gpio_info[FIRMWARE_MAX_CARD_SLOT_NUM]; /* private data */
|
||||
} firmware_card_info_t;
|
||||
|
||||
typedef enum card_type_e {
|
||||
RA_B6010_48GT4X = 0X4065,
|
||||
RA_B6010_48GT4X_R = 0X4065,
|
||||
} card_type_t;
|
||||
|
||||
extern firmware_card_info_t* firmware_get_card_info(int dev_type);
|
||||
extern int dfd_fpga_upgrade_do_upgrade(char* upg_file);
|
||||
extern int dfd_fpga_upgrade_test(void);
|
||||
extern int ispvme_test(void);
|
||||
extern int ispvme_main(int argc, char *argv[]);
|
||||
/* External fpga dump interface */
|
||||
extern int dfd_fpga_upgrade_dump_flash(int argc, char* argv[]);
|
||||
|
||||
#endif /* End of __FIRMWARE_APP_H__ */
|
@ -1,845 +0,0 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* Lattice Semiconductor Corp. Copyright 2008
|
||||
*
|
||||
* ispVME Embedded allows programming of Lattice's suite of FPGA
|
||||
* devices on embedded systems through the JTAG port. The software
|
||||
* is distributed in source code form and is open to re - distribution
|
||||
* and modification where applicable.
|
||||
*
|
||||
* ispVME Embedded C Source comprised with 3 modules:
|
||||
* ispvm_ui.c is the module provides input and output support.
|
||||
* ivm_core.c is the module interpret the VME file(s).
|
||||
* hardware.c is the module access the JTAG port of the device(s).
|
||||
*
|
||||
* The optional module cable.c is for supporting Lattice's parallel
|
||||
* port ispDOWNLOAD cable on DOS and Windows 95/98 O/S. It can be
|
||||
* requested from Lattice's ispVMSupport.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* Revision History of ispvm_ui.c
|
||||
*
|
||||
* 3/6/07 ht Added functions vme_out_char(),vme_out_hex(),
|
||||
* vme_out_string() to provide output resources.
|
||||
* Consolidate all printf() calls into the added output
|
||||
* functions.
|
||||
*
|
||||
* 09/11/07 NN Added Global variables initialization
|
||||
* 09/24/07 NN Added a switch allowing users to do calibration.
|
||||
* Calibration will help to determine the system clock frequency
|
||||
* and the count value for one micro-second delay of the target
|
||||
* specific hardware.
|
||||
* Removed Delay Percent support
|
||||
* 11/15/07 NN moved the checking of the File CRC to the end of processing
|
||||
* 08/28/08 NN Added Calculate checksum support.
|
||||
***************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <debug_ispvme.h>
|
||||
#include "vmopcode.h"
|
||||
#include "common.h"
|
||||
|
||||
#define dbg_print(debug, fmt, arg...) \
|
||||
if (debug == DEBUG_APP_ON || debug == DEBUG_ALL_ON) \
|
||||
{ do{printf(fmt,##arg);} while(0); }
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* File pointer to the VME file.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
FILE *g_pVMEFile = NULL;
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Functions declared in this ispvm_ui.c module
|
||||
*
|
||||
***************************************************************/
|
||||
unsigned char GetByte(void);
|
||||
void vme_out_char(unsigned char charOut);
|
||||
void vme_out_hex(unsigned char hexOut);
|
||||
void vme_out_string(char *stringOut);
|
||||
void ispVMMemManager(signed char cTarget, unsigned short usSize);
|
||||
void ispVMFreeMem(void);
|
||||
void error_handler(short a_siRetCode, char *pszMessage);
|
||||
signed char ispVM(const char *a_pszFilename);
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Global variables.
|
||||
*
|
||||
***************************************************************/
|
||||
unsigned short g_usPreviousSize = 0;
|
||||
unsigned short g_usExpectedCRC = 0;
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* External variables and functions declared in ivm_core.c module.
|
||||
*
|
||||
***************************************************************/
|
||||
extern signed char ispVMCode();
|
||||
extern void ispVMCalculateCRC32(unsigned char a_ucData);
|
||||
extern void ispVMStart();
|
||||
extern void ispVMEnd();
|
||||
extern void ispVMStateMachine(signed char NextState);
|
||||
extern void writePort(unsigned char a_ucPins, unsigned char a_ucValue);
|
||||
extern void sclock();
|
||||
extern unsigned char readPort();
|
||||
extern unsigned short g_usCalculatedCRC;
|
||||
extern unsigned short g_usDataType;
|
||||
extern unsigned char *g_pucOutMaskData,
|
||||
*g_pucInData,
|
||||
*g_pucOutData,
|
||||
*g_pucHIRData,
|
||||
*g_pucTIRData,
|
||||
*g_pucHDRData,
|
||||
*g_pucTDRData,
|
||||
*g_pucOutDMaskData,
|
||||
*g_pucIntelBuffer;
|
||||
extern unsigned char *g_pucHeapMemory;
|
||||
extern unsigned short g_iHeapCounter;
|
||||
extern unsigned short g_iHEAPSize;
|
||||
extern unsigned short g_usIntelDataIndex;
|
||||
extern unsigned short g_usIntelBufferSize;
|
||||
extern LVDSPair *g_pLVDSList;
|
||||
/* 08/28/08 NN Added Calculate checksum support. */
|
||||
extern unsigned long g_usChecksum;
|
||||
extern unsigned int g_uiChecksumIndex;
|
||||
/***************************************************************
|
||||
*
|
||||
* External variables and functions declared in hardware.c module.
|
||||
*
|
||||
***************************************************************/
|
||||
extern void calibration(void);
|
||||
extern unsigned short g_usCpu_Frequency;
|
||||
|
||||
static int is_debug_on = -1;
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Supported VME versions.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
const char *const g_szSupportedVersions[] = { "__VME2.0", "__VME3.0", "____12.0", "____12.1", 0 };
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* GetByte
|
||||
*
|
||||
* Returns a byte to the caller. The returned byte depends on the
|
||||
* g_usDataType register. If the HEAP_IN bit is set, then the byte
|
||||
* is returned from the HEAP. If the LHEAP_IN bit is set, then
|
||||
* the byte is returned from the intelligent buffer. Otherwise,
|
||||
* the byte is returned directly from the VME file.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
char* strlwr(char *str)
|
||||
{
|
||||
char *orig = str;
|
||||
/* process the string */
|
||||
for (; *str != '\0'; str++)
|
||||
*str = tolower(*str);
|
||||
return orig;
|
||||
}
|
||||
|
||||
unsigned char GetByte()
|
||||
{
|
||||
unsigned char ucData = 0;
|
||||
|
||||
if (g_usDataType & HEAP_IN) {
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Get data from repeat buffer.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
if (g_iHeapCounter > g_iHEAPSize) {
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Data over-run.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
ucData = g_pucHeapMemory[g_iHeapCounter++];
|
||||
}
|
||||
else if ( g_usDataType & LHEAP_IN ) {
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Get data from intel buffer.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
if (g_usIntelDataIndex >= g_usIntelBufferSize) {
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Data over-run.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
ucData = g_pucIntelBuffer[g_usIntelDataIndex++];
|
||||
}
|
||||
else {
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Get data from file.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
ucData = (unsigned char)fgetc(g_pVMEFile);
|
||||
|
||||
|
||||
if (feof(g_pVMEFile)) {
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Reached EOF.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
/***************************************************************
|
||||
*
|
||||
* Calculate the 32-bit CRC if the expected CRC exist.
|
||||
*
|
||||
***************************************************************/
|
||||
if( g_usExpectedCRC != 0)
|
||||
{
|
||||
ispVMCalculateCRC32(ucData);
|
||||
}
|
||||
}
|
||||
|
||||
return (ucData);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* vme_out_char
|
||||
*
|
||||
* Send a character out to the output resource if available.
|
||||
* The monitor is the default output resource.
|
||||
*
|
||||
*
|
||||
***************************************************************/
|
||||
void vme_out_char(unsigned char charOut)
|
||||
{
|
||||
dbg_print(is_debug_on, "%c", charOut);
|
||||
}
|
||||
/***************************************************************
|
||||
*
|
||||
* vme_out_hex
|
||||
*
|
||||
* Send a character out as in hex format to the output resource
|
||||
* if available. The monitor is the default output resource.
|
||||
*
|
||||
*
|
||||
***************************************************************/
|
||||
void vme_out_hex(unsigned char hexOut)
|
||||
{
|
||||
dbg_print(is_debug_on, "%.2X", hexOut);
|
||||
}
|
||||
/***************************************************************
|
||||
*
|
||||
* vme_out_string
|
||||
*
|
||||
* Send a text string out to the output resource if available.
|
||||
* The monitor is the default output resource.
|
||||
*
|
||||
*
|
||||
***************************************************************/
|
||||
void vme_out_string(char *stringOut)
|
||||
{
|
||||
if (is_debug_on == -1) {
|
||||
is_debug_on = firmware_upgrade_debug();
|
||||
}
|
||||
|
||||
dbg_print(is_debug_on, stringOut);
|
||||
}
|
||||
/***************************************************************
|
||||
*
|
||||
* ispVMMemManager
|
||||
*
|
||||
* Allocate memory based on cTarget. The memory size is specified
|
||||
* by usSize.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
void ispVMMemManager(signed char cTarget, unsigned short usSize)
|
||||
{
|
||||
switch (cTarget) {
|
||||
case XTDI:
|
||||
case TDI:
|
||||
if (g_pucInData != NULL) {
|
||||
if (g_usPreviousSize == usSize) { /*memory exist*/
|
||||
break;
|
||||
}
|
||||
else {
|
||||
free(g_pucInData);
|
||||
g_pucInData = NULL;
|
||||
}
|
||||
}
|
||||
g_pucInData = (unsigned char *)malloc(usSize / 8 + 2);
|
||||
g_usPreviousSize = usSize;
|
||||
case XTDO:
|
||||
case TDO:
|
||||
if (g_pucOutData != NULL) {
|
||||
if (g_usPreviousSize == usSize) { /*already exist*/
|
||||
break;
|
||||
}
|
||||
else {
|
||||
free(g_pucOutData);
|
||||
g_pucOutData = NULL;
|
||||
}
|
||||
}
|
||||
g_pucOutData = (unsigned char *)malloc(usSize / 8 + 2);
|
||||
g_usPreviousSize = usSize;
|
||||
break;
|
||||
case MASK:
|
||||
if (g_pucOutMaskData != NULL) {
|
||||
if (g_usPreviousSize == usSize) { /*already allocated*/
|
||||
break;
|
||||
}
|
||||
else {
|
||||
free(g_pucOutMaskData);
|
||||
g_pucOutMaskData = NULL;
|
||||
}
|
||||
}
|
||||
g_pucOutMaskData = (unsigned char *)malloc(usSize / 8 + 2);
|
||||
g_usPreviousSize = usSize;
|
||||
break;
|
||||
case HIR:
|
||||
if (g_pucHIRData != NULL) {
|
||||
free(g_pucHIRData);
|
||||
g_pucHIRData = NULL;
|
||||
}
|
||||
g_pucHIRData = (unsigned char *)malloc(usSize / 8 + 2);
|
||||
break;
|
||||
case TIR:
|
||||
if (g_pucTIRData != NULL) {
|
||||
free(g_pucTIRData);
|
||||
g_pucTIRData = NULL;
|
||||
}
|
||||
g_pucTIRData = (unsigned char *)malloc(usSize / 8 + 2);
|
||||
break;
|
||||
case HDR:
|
||||
if (g_pucHDRData != NULL) {
|
||||
free(g_pucHDRData);
|
||||
g_pucHDRData = NULL;
|
||||
}
|
||||
g_pucHDRData = (unsigned char *)malloc(usSize / 8 + 2);
|
||||
break;
|
||||
case TDR:
|
||||
if (g_pucTDRData != NULL) {
|
||||
free(g_pucTDRData);
|
||||
g_pucTDRData = NULL;
|
||||
}
|
||||
g_pucTDRData = (unsigned char *)malloc(usSize / 8 + 2);
|
||||
break;
|
||||
case HEAP:
|
||||
if (g_pucHeapMemory != NULL) {
|
||||
free(g_pucHeapMemory);
|
||||
g_pucHeapMemory = NULL;
|
||||
}
|
||||
g_pucHeapMemory = (unsigned char *)malloc(usSize + 2);
|
||||
break;
|
||||
case DMASK:
|
||||
if (g_pucOutDMaskData != NULL) {
|
||||
if (g_usPreviousSize == usSize) { /*already allocated*/
|
||||
break;
|
||||
}
|
||||
else {
|
||||
free(g_pucOutDMaskData);
|
||||
g_pucOutDMaskData = NULL;
|
||||
}
|
||||
}
|
||||
g_pucOutDMaskData = (unsigned char *)malloc(usSize / 8 + 2);
|
||||
g_usPreviousSize = usSize;
|
||||
break;
|
||||
case LHEAP:
|
||||
if (g_pucIntelBuffer != NULL) {
|
||||
free(g_pucIntelBuffer);
|
||||
g_pucIntelBuffer = NULL;
|
||||
}
|
||||
g_pucIntelBuffer = (unsigned char *)malloc(usSize + 2);
|
||||
break;
|
||||
case LVDS:
|
||||
if (g_pLVDSList != NULL) {
|
||||
free(g_pLVDSList);
|
||||
g_pLVDSList = NULL;
|
||||
}
|
||||
g_pLVDSList = (LVDSPair * )calloc(usSize, sizeof(LVDSPair));
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* ispVMFreeMem
|
||||
*
|
||||
* Free memory that were dynamically allocated.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
void ispVMFreeMem()
|
||||
{
|
||||
if (g_pucHeapMemory != NULL) {
|
||||
free(g_pucHeapMemory);
|
||||
g_pucHeapMemory = NULL;
|
||||
}
|
||||
|
||||
if (g_pucOutMaskData != NULL) {
|
||||
free(g_pucOutMaskData);
|
||||
g_pucOutMaskData = NULL;
|
||||
}
|
||||
|
||||
if (g_pucInData != NULL) {
|
||||
free(g_pucInData);
|
||||
g_pucInData = NULL;
|
||||
}
|
||||
|
||||
if (g_pucOutData != NULL) {
|
||||
free(g_pucOutData);
|
||||
g_pucOutData = NULL;
|
||||
}
|
||||
|
||||
if (g_pucHIRData != NULL) {
|
||||
free(g_pucHIRData);
|
||||
g_pucHIRData = NULL;
|
||||
}
|
||||
|
||||
if (g_pucTIRData != NULL) {
|
||||
free(g_pucTIRData);
|
||||
g_pucTIRData = NULL;
|
||||
}
|
||||
|
||||
if (g_pucHDRData != NULL) {
|
||||
free(g_pucHDRData);
|
||||
g_pucHDRData = NULL;
|
||||
}
|
||||
|
||||
if (g_pucTDRData != NULL) {
|
||||
free(g_pucTDRData);
|
||||
g_pucTDRData = NULL;
|
||||
}
|
||||
|
||||
if (g_pucOutDMaskData != NULL) {
|
||||
free(g_pucOutDMaskData);
|
||||
g_pucOutDMaskData = NULL;
|
||||
}
|
||||
|
||||
if (g_pucIntelBuffer != NULL) {
|
||||
free(g_pucIntelBuffer);
|
||||
g_pucIntelBuffer = NULL;
|
||||
}
|
||||
|
||||
if (g_pLVDSList != NULL) {
|
||||
free(g_pLVDSList);
|
||||
g_pLVDSList = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* error_handler
|
||||
*
|
||||
* Reports the error message.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
void error_handler(short a_siRetCode, char *pszMessage)
|
||||
{
|
||||
const char *pszErrorMessage[] = { "pass",
|
||||
"verification fail",
|
||||
"can't find the file",
|
||||
"wrong file type",
|
||||
"file error",
|
||||
"option error",
|
||||
"crc verification error" };
|
||||
|
||||
strcpy(pszMessage, pszErrorMessage[-a_siRetCode]);
|
||||
}
|
||||
/***************************************************************
|
||||
*
|
||||
* ispVM
|
||||
*
|
||||
* The entry point of the ispVM embedded. If the version and CRC
|
||||
* are verified, then the VME will be processed.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
signed char ispVM(const char *a_pszFilename)
|
||||
{
|
||||
char szFileVersion[9] = { 0 };
|
||||
signed char cRetCode = 0;
|
||||
signed char cIndex = 0;
|
||||
signed char cVersionIndex = 0;
|
||||
unsigned char ucReadByte = 0;
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Global variables initialization.
|
||||
*
|
||||
* 09/11/07 NN Added
|
||||
***************************************************************/
|
||||
g_pucHeapMemory = NULL;
|
||||
g_iHeapCounter = 0;
|
||||
g_iHEAPSize = 0;
|
||||
g_usIntelDataIndex = 0;
|
||||
g_usIntelBufferSize = 0;
|
||||
g_usPreviousSize = 0;
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Open a file pointer to the VME file.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
|
||||
|
||||
if ((g_pVMEFile = fopen(a_pszFilename, "rb")) == NULL) {
|
||||
return VME_FILE_READ_FAILURE;
|
||||
}
|
||||
g_usCalculatedCRC = 0;
|
||||
g_usExpectedCRC = 0;
|
||||
ucReadByte = GetByte();
|
||||
//dbg_print(is_debug_on, "data: 0x%x.\n", ucReadByte);
|
||||
switch (ucReadByte) {
|
||||
case FILE_CRC:
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Read and store the expected CRC to do the comparison at the end.
|
||||
* Only versions 3.0 and higher support CRC protection.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
g_usExpectedCRC = (unsigned char)fgetc(g_pVMEFile);
|
||||
g_usExpectedCRC <<= 8;
|
||||
g_usExpectedCRC |= fgetc(g_pVMEFile);
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Read and store the version of the VME file.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
|
||||
for (cIndex = 0; cIndex < 8; cIndex++) {
|
||||
szFileVersion[cIndex] = GetByte();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Read and store the version of the VME file. Must be version 2.0.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
szFileVersion[0] = (signed char)ucReadByte;
|
||||
for (cIndex = 1; cIndex < 8; cIndex++) {
|
||||
szFileVersion[cIndex] = GetByte();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Compare the VME file version against the supported version.
|
||||
*
|
||||
***************************************************************/
|
||||
/* check the file version: the value of 0x03-0x0a */
|
||||
for (cVersionIndex = 0; g_szSupportedVersions[cVersionIndex] != 0; cVersionIndex++) {
|
||||
for (cIndex = 0; cIndex < 8; cIndex++) {
|
||||
if (szFileVersion[cIndex] != g_szSupportedVersions[cVersionIndex][cIndex]) {
|
||||
cRetCode = VME_VERSION_FAILURE;
|
||||
break;
|
||||
}
|
||||
cRetCode = 0;
|
||||
}
|
||||
|
||||
if (cRetCode == 0) {
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Found matching version, break.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cRetCode < 0) {
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* VME file version failed to match the supported versions.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
fclose(g_pVMEFile);
|
||||
g_pVMEFile = NULL;
|
||||
return VME_VERSION_FAILURE;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Enable the JTAG port to communicate with the device.
|
||||
* Set the JTAG state machine to the Test-Logic/Reset State.
|
||||
*
|
||||
***************************************************************/
|
||||
ispVMStart();
|
||||
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Process the VME file.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
cRetCode = ispVMCode();
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Set the JTAG State Machine to Test-Logic/Reset state then disable
|
||||
* the communication with the JTAG port.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
ispVMEnd();
|
||||
|
||||
fclose(g_pVMEFile);
|
||||
g_pVMEFile = NULL;
|
||||
|
||||
ispVMFreeMem();
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Compare the expected CRC versus the calculated CRC.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
if (cRetCode == 0 && g_usExpectedCRC != 0 && (g_usExpectedCRC != g_usCalculatedCRC)) {
|
||||
printf("Expected CRC: 0x%.4X\n", g_usExpectedCRC);
|
||||
printf("Calculated CRC: 0x%.4X\n", g_usCalculatedCRC);
|
||||
return VME_CRC_FAILURE;
|
||||
}
|
||||
|
||||
return (cRetCode);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* main
|
||||
*
|
||||
***************************************************************/
|
||||
extern int g_file_fd;
|
||||
int ispvme_main(int argc, char *argv[])
|
||||
{
|
||||
unsigned short iCommandLineIndex = 0;
|
||||
short siRetCode = 0;
|
||||
char szExtension[5] = { 0 };
|
||||
char szCommandLineArg[300] = { 0 };
|
||||
short sicalibrate = 0;
|
||||
|
||||
/* 08/28/08 NN Added Calculate checksum support. */
|
||||
g_usChecksum = 0;
|
||||
g_uiChecksumIndex = 0;
|
||||
|
||||
g_file_fd = open("/dev/firmware_cpld_ispvme0", O_RDWR);
|
||||
if (g_file_fd < 0) {
|
||||
printf("can't open device\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vme_out_string(" Lattice Semiconductor Corp.\n");
|
||||
vme_out_string("\n ispVME(tm) V");
|
||||
vme_out_string(VME_VERSION_NUMBER);
|
||||
vme_out_string(" Copyright 1998-2011.\n");
|
||||
vme_out_string("\nFor daisy chain programming of all in-system programmable devices\n\n");
|
||||
|
||||
if (argc < 2) {
|
||||
vme_out_string("\nUsage: vme [option] vme_file [vme_file]\n");
|
||||
vme_out_string("Example: vme vme_file1.vme vme_file2.vme\n");
|
||||
vme_out_string("option -c: do the calibration.\n");
|
||||
vme_out_string("Example: vme -c\n");
|
||||
vme_out_string("Example: vme -c vme_file1.vme vme_file2.vme\n");
|
||||
vme_out_string("\n\n");
|
||||
close(g_file_fd);
|
||||
return -1; /* Used by superiors to judge whether the upgrade is successful */
|
||||
//exit(1);
|
||||
}
|
||||
for (iCommandLineIndex = 1; iCommandLineIndex < argc; iCommandLineIndex++) {
|
||||
strcpy(szCommandLineArg, argv[iCommandLineIndex]);
|
||||
if (!strcmp(strlwr(szCommandLineArg), "-c") && (iCommandLineIndex == 1)) {
|
||||
sicalibrate = 1;
|
||||
} else if (!strcmp(strlwr(szCommandLineArg), "-c") && (iCommandLineIndex != 1)) {
|
||||
vme_out_string("Error: calibrate option -c must be the first argument\n\n");
|
||||
close(g_file_fd);
|
||||
return -1; /* Used by superiors to judge whether the upgrade is successful */
|
||||
//exit(1);
|
||||
} else {
|
||||
strcpy(szExtension, &szCommandLineArg[strlen(szCommandLineArg) - 4]);
|
||||
strlwr(szExtension);
|
||||
if (strcmp(szExtension, ".vme")) {
|
||||
vme_out_string("Error: VME files must end with the extension *.vme\n\n");
|
||||
close(g_file_fd);
|
||||
return -1; /* Used by superiors to judge whether the upgrade is successful */
|
||||
//exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
siRetCode = 0;
|
||||
|
||||
if (sicalibrate) {
|
||||
calibration();
|
||||
}
|
||||
for (iCommandLineIndex = 1; iCommandLineIndex < argc; iCommandLineIndex++) { /* Process all VME files sequentially */
|
||||
strcpy(szCommandLineArg, argv[iCommandLineIndex]);
|
||||
if (!strcmp(strlwr(szCommandLineArg), "-c") && (iCommandLineIndex == 1)) {
|
||||
|
||||
} else if (!strcmp(strlwr(szCommandLineArg), "-checksum")) {
|
||||
|
||||
} else {
|
||||
vme_out_string("Processing virtual machine file (");
|
||||
vme_out_string(szCommandLineArg);
|
||||
vme_out_string(")......\n\n");
|
||||
siRetCode = ispVM(szCommandLineArg);
|
||||
if (siRetCode < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (siRetCode < 0) {
|
||||
error_handler(siRetCode, szCommandLineArg);
|
||||
vme_out_string("Failed due to ");
|
||||
vme_out_string(szCommandLineArg);
|
||||
vme_out_string("\n\n");
|
||||
vme_out_string("+=======+\n");
|
||||
vme_out_string("| FAIL! |\n");
|
||||
vme_out_string("+=======+\n\n");
|
||||
} else {
|
||||
vme_out_string("+=======+\n");
|
||||
vme_out_string("| PASS! |\n");
|
||||
vme_out_string("+=======+\n\n");
|
||||
/* 08/28/08 NN Added Calculate checksum support. */
|
||||
if (g_usChecksum != 0) {
|
||||
g_usChecksum &= 0xFFFF;
|
||||
printf("Data Checksum: %.4X\n\n", (unsigned int)g_usChecksum);
|
||||
g_usChecksum = 0;
|
||||
}
|
||||
}
|
||||
close(g_file_fd);
|
||||
return siRetCode; /* Used by superiors to judge whether the upgrade is successful */
|
||||
//exit(siRetCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* function:CPLD online upgrade channel test program
|
||||
* input parameters: None
|
||||
* output parameters:None
|
||||
* return: 0 means test successfully -1 means test failed
|
||||
*/
|
||||
int ispvme_test(void)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char index = 0;
|
||||
unsigned char indata = 0,outdata = 0;
|
||||
unsigned char datasize = 8;
|
||||
unsigned int tmpdata = 0;
|
||||
char curbit = 0;
|
||||
int nDevices = 0;
|
||||
|
||||
g_file_fd = open("/dev/firmware_cpld_ispvme0", O_RDWR);
|
||||
if (g_file_fd < 0) {
|
||||
printf("can't open device\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* go to Shift-IR */
|
||||
ispVMStart();
|
||||
ispVMStateMachine(IDLE);
|
||||
ispVMStateMachine(IRPAUSE);
|
||||
ispVMStateMachine(SHIFTIR);
|
||||
|
||||
/* Send plenty of ones into the IR registers,that makes sure all devices are in BYPASS! */
|
||||
for (index = 0; index < 100; index++) {
|
||||
writePort(JTAG_TDI, 1);
|
||||
sclock();
|
||||
}
|
||||
|
||||
/* exit Shift-IR,and go to Shift-DR */
|
||||
ispVMStateMachine(IRPAUSE);
|
||||
ispVMStateMachine(DRPAUSE);
|
||||
ispVMStateMachine(SHIFTDR);
|
||||
|
||||
/* Send plenty of zeros into the DR registers to flush them */
|
||||
for (index = 0; index < 100; index++) {
|
||||
writePort(JTAG_TDI, 0);
|
||||
sclock();
|
||||
}
|
||||
|
||||
/* now send ones until we receive one back,to find out number of device(s) */
|
||||
for(index = 0; index < 100; index++){
|
||||
writePort(JTAG_TDI, 1);
|
||||
sclock();
|
||||
curbit = readPort();
|
||||
if(1 == curbit){
|
||||
nDevices = index + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*flush again */
|
||||
for (index = 0; index < 100; index++) {
|
||||
writePort(JTAG_TDI, 0);
|
||||
sclock();
|
||||
}
|
||||
|
||||
/* test data probe */
|
||||
indata = 0x5a;
|
||||
for (index = 0; index < datasize + nDevices; index++) {
|
||||
tmpdata <<= 1;
|
||||
curbit = readPort();
|
||||
tmpdata |= curbit;
|
||||
writePort(JTAG_TDI, ((indata << index) & 0x80) ? 0x01:0x00);
|
||||
sclock();
|
||||
}
|
||||
outdata = (tmpdata & 0xFF);
|
||||
if(outdata != indata){
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* go to Test-Logic-Reset */
|
||||
ispVMStateMachine(IDLE);
|
||||
ispVMStart();
|
||||
|
||||
/* close ispvme */
|
||||
close(g_file_fd);
|
||||
return ret;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,192 +0,0 @@
|
||||
/***************************************************************
|
||||
*
|
||||
* This is the include file for Lattice Semiconductor's ispVM
|
||||
* Embedded software application.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* VME version.
|
||||
*
|
||||
* History:
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
#define VME_VERSION_NUMBER "12.2"
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Maximum declarations.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
#define VMEHEXMAX 60000L /* The hex file is split 60K per file. */
|
||||
#define SCANMAX 64000L /* The maximum SDR/SIR burst. */
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Supported JTAG state transitions.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
#define RESET 0x00
|
||||
#define IDLE 0x01
|
||||
#define IRPAUSE 0x02
|
||||
#define DRPAUSE 0x03
|
||||
#define SHIFTIR 0x04
|
||||
#define SHIFTDR 0x05
|
||||
#define DRCAPTURE 0x06
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Flow control register bit definitions. A set bit indicates
|
||||
* that the register currently exhibits the corresponding mode.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
#define INTEL_PRGM 0x0001 /* Intelligent programming is in effect. */
|
||||
#define CASCADE 0x0002 /* Currently splitting large SDR. */
|
||||
#define REPEATLOOP 0x0008 /* Currently executing a repeat loop. */
|
||||
#define SHIFTRIGHT 0x0080 /* The next data stream needs a right shift. */
|
||||
#define SHIFTLEFT 0x0100 /* The next data stream needs a left shift. */
|
||||
#define VERIFYUES 0x0200 /* Continue if fail is in effect. */
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* DataType register bit definitions. A set bit indicates
|
||||
* that the register currently holds the corresponding type of data.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
#define EXPRESS 0x0001 /* Simultaneous program and verify. */
|
||||
#define SIR_DATA 0x0002 /* SIR is the active SVF command. */
|
||||
#define SDR_DATA 0x0004 /* SDR is the active SVF command. */
|
||||
#define COMPRESS 0x0008 /* Data is compressed. */
|
||||
#define TDI_DATA 0x0010 /* TDI data is present. */
|
||||
#define TDO_DATA 0x0020 /* TDO data is present. */
|
||||
#define MASK_DATA 0x0040 /* MASK data is present. */
|
||||
#define HEAP_IN 0x0080 /* Data is from the heap. */
|
||||
#define LHEAP_IN 0x0200 /* Data is from intel data buffer. */
|
||||
#define VARIABLE 0x0400 /* Data is from a declared variable. */
|
||||
#define CRC_DATA 0x0800 /* CRC data is pressent. */
|
||||
#define CMASK_DATA 0x1000 /* CMASK data is pressent. */
|
||||
#define RMASK_DATA 0x2000 /* RMASK data is pressent. */
|
||||
#define READ_DATA 0x4000 /* READ data is pressent. */
|
||||
#define DMASK_DATA 0x8000 /* DMASK data is pressent. */
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Pin opcodes.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
#define signalENABLE 0x1C /* ispENABLE pin. */
|
||||
#define signalTMS 0x1D /* TMS pin. */
|
||||
#define signalTCK 0x1E /* TCK pin. */
|
||||
#define signalTDI 0x1F /* TDI pin. */
|
||||
#define signalTRST 0x20 /* TRST pin. */
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Supported vendors.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
#define VENDOR 0x56
|
||||
#define LATTICE 0x01
|
||||
#define ALTERA 0x02
|
||||
#define XILINX 0x03
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Opcode definitions.
|
||||
*
|
||||
* Note: opcodes must be unique.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
#define ENDDATA 0x00 /* The end of the current SDR data stream. */
|
||||
#define RUNTEST 0x01 /* The duration to stay at the stable state. */
|
||||
#define ENDDR 0x02 /* The stable state after SDR. */
|
||||
#define ENDIR 0x03 /* The stable state after SIR. */
|
||||
#define ENDSTATE 0x04 /* The stable state after RUNTEST. */
|
||||
#define TRST 0x05 /* Assert the TRST pin. */
|
||||
#define HIR 0x06 /* The sum of the IR bits of the leading devices. */
|
||||
#define TIR 0x07 /* The sum of the IR bits of the trailing devices. */
|
||||
#define HDR 0x08 /* The number of leading devices. */
|
||||
#define TDR 0x09 /* The number of trailing devices. */
|
||||
#define ispEN 0x0A /* Assert the ispEN pin. */
|
||||
#define FREQUENCY 0x0B /* The maximum clock rate to run the JTAG state machine. */
|
||||
#define STATE 0x10 /* Move to the next stable state. */
|
||||
#define SIR 0x11 /* The instruction stream follows. */
|
||||
#define SDR 0x12 /* The data stream follows. */
|
||||
#define TDI 0x13 /* The following data stream feeds into the device. */
|
||||
#define TDO 0x14 /* The following data stream is compared against the device. */
|
||||
#define MASK 0x15 /* The following data stream is used as mask. */
|
||||
#define XSDR 0x16 /* The following data stream is for simultaneous program and verify. */
|
||||
#define XTDI 0x17 /* The following data stream is for shift in only. It must be stored for the next XSDR. */
|
||||
#define XTDO 0x18 /* There is not data stream. The data stream was stored from the previous XTDI. */
|
||||
#define MEM 0x19 /* The maximum memory needed to allocate in order hold one row of data. */
|
||||
#define WAIT 0x1A /* The duration of delay to observe. */
|
||||
#define TCK 0x1B /* The number of TCK pulses. */
|
||||
#define SHR 0x23 /* Set the flow control register for right shift. */
|
||||
#define SHL 0x24 /* Set the flow control register for left shift. */
|
||||
#define HEAP 0x32 /* The memory size needed to hold one loop. */
|
||||
#define REPEAT 0x33 /* The beginning of the loop. */
|
||||
#define LEFTPAREN 0x35 /* The beginning of data following the loop. */
|
||||
#define VAR 0x55 /* Plac holder for loop data. */
|
||||
#define SEC 0x1C /* The delay time in seconds that must be observed. */
|
||||
#define SMASK 0x1D /* The mask for TDI data. */
|
||||
#define MAX 0x1E /* The absolute maximum wait time. */
|
||||
#define ON 0x1F /* Assert the targeted pin. */
|
||||
#define OFF 0x20 /* Dis-assert the targeted pin. */
|
||||
#define SETFLOW 0x30 /* Change the flow control register. */
|
||||
#define RESETFLOW 0x31 /* Clear the flow control register. */
|
||||
#define CRC 0x47 /* The following data stream is used for CRC calculation. */
|
||||
#define CMASK 0x48 /* The following data stream is used as mask for CRC calculation. */
|
||||
#define RMASK 0x49 /* The following data stream is used as mask for read and save. */
|
||||
#define READ 0x50 /* The following data stream is used for read and save. */
|
||||
#define ENDLOOP 0x59 /* The end of the repeat loop. */
|
||||
#define SECUREHEAP 0x60 /* Used to secure the HEAP opcode. */
|
||||
#define VUES 0x61 /* Support continue if fail. */
|
||||
#define DMASK 0x62 /* The following data stream is used for dynamic I/O. */
|
||||
#define COMMENT 0x63 /* Support SVF comments in the VME file. */
|
||||
#define HEADER 0x64 /* Support header in VME file. */
|
||||
#define FILE_CRC 0x65 /* Support crc-protected VME file. */
|
||||
#define LCOUNT 0x66 /* Support intelligent programming. */
|
||||
#define LDELAY 0x67 /* Support intelligent programming. */
|
||||
#define LSDR 0x68 /* Support intelligent programming. */
|
||||
#define LHEAP 0x69 /* Memory needed to hold intelligent data buffer */
|
||||
#define CONTINUE 0x70 /* Allow continuation. */
|
||||
#define LVDS 0x71 /* Support LVDS. */
|
||||
#define ENDVME 0x7F /* End of the VME file. */
|
||||
#define HIGH 0x80 /* Assert the targeted pin. */
|
||||
#define LOW 0x81 /* Dis-assert the targeted pin. */
|
||||
#define ENDFILE 0xFF /* End of file. */
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* ispVM Embedded Return Codes.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
#define VME_VERIFICATION_FAILURE -1
|
||||
#define VME_FILE_READ_FAILURE -2
|
||||
#define VME_VERSION_FAILURE -3
|
||||
#define VME_INVALID_FILE -4
|
||||
#define VME_ARGUMENT_FAILURE -5
|
||||
#define VME_CRC_FAILURE -6
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Type definitions.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
/* Support LVDS */
|
||||
typedef struct {
|
||||
unsigned short usPositiveIndex;
|
||||
unsigned short usNegativeIndex;
|
||||
unsigned char ucUpdate;
|
||||
} LVDSPair;
|
Binary file not shown.
@ -1,210 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
class FantlvException(Exception):
|
||||
def __init__(self, message='fantlverror', code=-100):
|
||||
err = 'errcode: {0} message:{1}'.format(code, message)
|
||||
Exception.__init__(self, err)
|
||||
self.code = code
|
||||
self.message = message
|
||||
|
||||
class fan_tlv(object):
|
||||
HEAD_INFO = "\x01\x7e\x01\xf1"
|
||||
VERSION = 0x01 # E2PROM file init version is 0x01
|
||||
FLAG = 0x7E # new version E2PROM mark as 0x7E
|
||||
HW_VER = 0X01 # consists of master version and revised version
|
||||
TYPE = 0xf1 # hardware type define
|
||||
TLV_LEN = 00 # vaild data length(16bit)
|
||||
_FAN_TLV_HDR_LEN = 6
|
||||
_FAN_TLV_CRC_LEN = 2
|
||||
|
||||
_FAN_TLV_TYPE_NAME = 0x02
|
||||
_FAN_TLV_TYPE_SN = 0x03
|
||||
_FAN_TLV_TYPE_HW_INFO = 0x05
|
||||
_FAN_TLV_TYPE_DEV_TYPE = 0x06
|
||||
|
||||
_fandecodetime = 0
|
||||
|
||||
@property
|
||||
def dstatus(self):
|
||||
return self._dstatus
|
||||
|
||||
@property
|
||||
def typename(self):
|
||||
return self._typename
|
||||
|
||||
@property
|
||||
def typesn(self):
|
||||
return self._typesn
|
||||
|
||||
@property
|
||||
def typehwinfo(self):
|
||||
return self._typehwinfo
|
||||
|
||||
@property
|
||||
def typedevtype(self):
|
||||
return self._typedevtype
|
||||
|
||||
@property
|
||||
def fanbus(self):
|
||||
return self._fanbus
|
||||
|
||||
@property
|
||||
def fanloc(self):
|
||||
return self._fanloc
|
||||
|
||||
@property
|
||||
def fandecodetime(self):
|
||||
return self._fandecodetime
|
||||
|
||||
def __init__(self):
|
||||
self._typename = ""
|
||||
self._typesn = ""
|
||||
self._typehwinfo = ""
|
||||
self._typedevtype = ""
|
||||
self._dstatus = 0
|
||||
|
||||
def strtoarr(self, str):
|
||||
s = []
|
||||
if str is not None:
|
||||
for index in range(len(str)):
|
||||
s.append(str[index])
|
||||
return s
|
||||
|
||||
def str_to_hex(self,rest_v):
|
||||
value = 0
|
||||
for index in range(len(rest_v)):
|
||||
value |= ord(rest_v[index]) << ((len(rest_v) - index - 1) * 8)
|
||||
return value
|
||||
|
||||
def hex_to_str(self,s):
|
||||
len_t = len(s)
|
||||
if len_t % 2 != 0:
|
||||
return 0
|
||||
ret = ""
|
||||
for t in range(0, int(len_t / 2)):
|
||||
ret += chr(int(s[2 * t:2 * t + 2], 16))
|
||||
return ret
|
||||
|
||||
def generate_fan_value(self):
|
||||
bin_buffer = [chr(0xff)] * 256
|
||||
bin_buffer[0] = chr(self.VERSION)
|
||||
bin_buffer[1] = chr(self.FLAG)
|
||||
bin_buffer[2] = chr(self.HW_VER)
|
||||
bin_buffer[3] = chr(self.TYPE)
|
||||
|
||||
temp_t = "%08x" % self.typedevtype # handle devtype first
|
||||
typedevtype_t = self.hex_to_str(temp_t)
|
||||
total_len = len(self.typename) + len(self.typesn) + \
|
||||
len(self.typehwinfo) + len(typedevtype_t) + 8
|
||||
|
||||
bin_buffer[4] = chr(total_len >> 8)
|
||||
bin_buffer[5] = chr(total_len & 0x00FF)
|
||||
|
||||
index_start = 6
|
||||
bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_NAME)
|
||||
bin_buffer[index_start + 1] = chr(len(self.typename))
|
||||
bin_buffer[index_start + 2: index_start + 2 +
|
||||
len(self.typename)] = self.strtoarr(self.typename)
|
||||
index_start = index_start + 2 + len(self.typename)
|
||||
|
||||
bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_SN)
|
||||
bin_buffer[index_start + 1] = chr(len(self.typesn))
|
||||
bin_buffer[index_start + 2:index_start + 2 +
|
||||
len(self.typesn)] = self.strtoarr(self.typesn)
|
||||
index_start = index_start + 2 + len(self.typesn)
|
||||
|
||||
bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_HW_INFO)
|
||||
bin_buffer[index_start + 1] = chr(len(self.typehwinfo))
|
||||
bin_buffer[index_start + 2:index_start + 2 +
|
||||
len(self.typehwinfo)] = self.strtoarr(self.typehwinfo)
|
||||
index_start = index_start + 2 + len(self.typehwinfo)
|
||||
|
||||
bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_DEV_TYPE)
|
||||
bin_buffer[index_start + 1] = chr(len(typedevtype_t))
|
||||
bin_buffer[index_start + 2:index_start + 2 +
|
||||
len(typedevtype_t)] = self.strtoarr(typedevtype_t)
|
||||
index_start = index_start + 2 + len(typedevtype_t)
|
||||
|
||||
crcs = fan_tlv.fancrc(''.join(bin_buffer[0:index_start])) # 2bytes checking
|
||||
bin_buffer[index_start] = chr(crcs >> 8)
|
||||
bin_buffer[index_start + 1] = chr(crcs & 0x00ff)
|
||||
# printvalue(bin_buffer)
|
||||
return bin_buffer
|
||||
|
||||
def decode(self, e2):
|
||||
if e2[0:4] != self.HEAD_INFO:
|
||||
raise FantlvException("Fan tlv head info error,not fan tlv type", -10)
|
||||
ret = []
|
||||
self.VERSION = ord(e2[0])
|
||||
self.FLAG = ord(e2[1])
|
||||
self.HW_VER = ord(e2[2])
|
||||
self.TYPE = ord(e2[3])
|
||||
self.TLV_LEN = (ord(e2[4]) << 8) | ord(e2[5])
|
||||
|
||||
tlv_index = self._FAN_TLV_HDR_LEN
|
||||
tlv_end = self._FAN_TLV_HDR_LEN + self.TLV_LEN
|
||||
|
||||
# check sum
|
||||
if len(e2) < self._FAN_TLV_HDR_LEN + self.TLV_LEN + 2:
|
||||
raise FantlvException("Fan tlv eeprom len error!", -2)
|
||||
sumcrc = fan_tlv.fancrc(e2[0:self._FAN_TLV_HDR_LEN + self.TLV_LEN])
|
||||
readcrc = ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN]
|
||||
) << 8 | ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN + 1])
|
||||
if sumcrc != readcrc:
|
||||
raise FantlvException("Fan tlv eeprom checksum error!", -1)
|
||||
else:
|
||||
self._dstatus = 0
|
||||
while (tlv_index + 2) < len(e2) and tlv_index < tlv_end:
|
||||
s = self.decoder(
|
||||
e2[tlv_index:tlv_index + 2 + ord(e2[tlv_index + 1])])
|
||||
tlv_index += ord(e2[tlv_index + 1]) + 2
|
||||
ret.append(s)
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def fancrc(t):
|
||||
sum = 0
|
||||
for index in range(len(t)):
|
||||
sum += ord(t[index])
|
||||
return sum
|
||||
|
||||
def decoder(self, t):
|
||||
try:
|
||||
name = ""
|
||||
value = ""
|
||||
_len = ord(t[1])
|
||||
if ord(t[0]) == self._FAN_TLV_TYPE_NAME:
|
||||
name = "Product Name"
|
||||
value = t[2:2 + ord(t[1])]
|
||||
self._typename = value
|
||||
elif ord(t[0]) == self._FAN_TLV_TYPE_SN:
|
||||
name = "serial Number"
|
||||
value = t[2:2 + ord(t[1])]
|
||||
self._typesn = value
|
||||
elif ord(t[0]) == self._FAN_TLV_TYPE_HW_INFO:
|
||||
name = "hardware info"
|
||||
value = t[2:2 + ord(t[1])]
|
||||
self._typehwinfo = value
|
||||
elif ord(t[0]) == self._FAN_TLV_TYPE_DEV_TYPE:
|
||||
name = "dev type"
|
||||
value = "0x"
|
||||
for c in t[2:2 + ord(t[1])]:
|
||||
value += "%02X" % (ord(c),)
|
||||
self._typedevtype = int(value,16)
|
||||
return {"name": name, "code": ord(t[0]), "value": value,"lens": _len}
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return None
|
||||
|
||||
def __str__(self):
|
||||
formatstr = "VERSION : 0x%02x \n" \
|
||||
" FLAG : 0x%02x \n" \
|
||||
" HW_VER : 0x%02x \n" \
|
||||
" TYPE : 0x%02x \n" \
|
||||
"typename : %s \n" \
|
||||
"typesn : %s \n" \
|
||||
"typehwinfo : %s \n"
|
||||
return formatstr % (self.VERSION, self.FLAG, self.HW_VER, self.TYPE, self.typename, self.typesn, self.typehwinfo)
|
||||
|
||||
|
@ -1,957 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import collections
|
||||
from bitarray import bitarray
|
||||
from datetime import datetime, timedelta
|
||||
import sys
|
||||
|
||||
__all__ = ["FruException", "FruUtil", "BaseArea", "BoardInfoArea", "ProductInfoArea",
|
||||
"MultiRecordArea", "Field", "ipmifru"]
|
||||
|
||||
__DEBUG__ = "N"
|
||||
|
||||
|
||||
class FruException(Exception):
|
||||
def __init__(self, message='fruerror', code=-100):
|
||||
err = 'errcode: {0} message:{1}'.format(code, message)
|
||||
Exception.__init__(self, err)
|
||||
self.code = code
|
||||
self.message = message
|
||||
|
||||
|
||||
def e_print(err):
|
||||
print("ERROR: " + err)
|
||||
|
||||
|
||||
def d_print(debug_info):
|
||||
if(__DEBUG__ == "Y"):
|
||||
print(debug_info)
|
||||
|
||||
|
||||
class FruUtil():
|
||||
@staticmethod
|
||||
def decodeLength(value):
|
||||
a = bitarray(8)
|
||||
a.setall(True)
|
||||
a[0:1] = 0
|
||||
a[1:2] = 0
|
||||
x = ord(a.tobytes())
|
||||
return x & ord(value)
|
||||
|
||||
@staticmethod
|
||||
def minToData():
|
||||
starttime = datetime(1996, 1, 1, 0, 0, 0)
|
||||
endtime = datetime.now()
|
||||
seconds = (endtime - starttime).total_seconds()
|
||||
mins = seconds / 60
|
||||
m = int(round(mins))
|
||||
return m
|
||||
|
||||
@staticmethod
|
||||
def getTimeFormat():
|
||||
return datetime.now().strftime('%Y-%m-%d')
|
||||
|
||||
@staticmethod
|
||||
def getTypeLength(value):
|
||||
if value is None:
|
||||
return 0
|
||||
a = bitarray(8)
|
||||
a.setall(False)
|
||||
a[0:1] = 1
|
||||
a[1:2] = 1
|
||||
x = ord(a.tobytes())
|
||||
return x | len(value)
|
||||
|
||||
@staticmethod
|
||||
def checksum(b):
|
||||
result = 0
|
||||
for i in range(len(b)):
|
||||
result += ord(b[i])
|
||||
return (0x100 - (result & 0xff)) & 0xff
|
||||
|
||||
|
||||
class BaseArea(object):
|
||||
SUGGESTED_SIZE_COMMON_HEADER = 8
|
||||
SUGGESTED_SIZE_INTERNAL_USE_AREA = 72
|
||||
SUGGESTED_SIZE_CHASSIS_INFO_AREA = 32
|
||||
SUGGESTED_SIZE_BOARD_INFO_AREA = 80
|
||||
SUGGESTED_SIZE_PRODUCT_INFO_AREA = 80
|
||||
|
||||
INITVALUE = b'\x00'
|
||||
resultvalue = INITVALUE * 256
|
||||
COMMON_HEAD_VERSION = b'\x01'
|
||||
__childList = None
|
||||
|
||||
def __init__(self, name="", size=0, offset=0):
|
||||
self.__childList = []
|
||||
self._offset = offset
|
||||
self.name = name
|
||||
self._size = size
|
||||
self._isPresent = False
|
||||
self._data = b'\x00' * size
|
||||
self.__dataoffset = 0
|
||||
|
||||
@property
|
||||
def childList(self):
|
||||
return self.__childList
|
||||
|
||||
@childList.setter
|
||||
def childList(self, value):
|
||||
self.__childList = value
|
||||
|
||||
@property
|
||||
def offset(self):
|
||||
return self._offset
|
||||
|
||||
@offset.setter
|
||||
def offset(self, value):
|
||||
self._offset = value
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
return self._size
|
||||
|
||||
@size.setter
|
||||
def size(self, value):
|
||||
self._size = value
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return self._data
|
||||
|
||||
@data.setter
|
||||
def data(self, value):
|
||||
self._data = value
|
||||
|
||||
@property
|
||||
def isPresent(self):
|
||||
return self._isPresent
|
||||
|
||||
@isPresent.setter
|
||||
def isPresent(self, value):
|
||||
self._isPresent = value
|
||||
|
||||
|
||||
class InternalUseArea(BaseArea):
|
||||
pass
|
||||
|
||||
|
||||
class ChassisInfoArea(BaseArea):
|
||||
pass
|
||||
|
||||
|
||||
class BoardInfoArea(BaseArea):
|
||||
_boardTime = None
|
||||
_fields = None
|
||||
_mfg_date = None
|
||||
|
||||
def __str__(self):
|
||||
formatstr = "version : %x\n" \
|
||||
"length : %d \n" \
|
||||
"language : %x \n" \
|
||||
"mfg_date : %s \n" \
|
||||
"boardManufacturer : %s \n" \
|
||||
"boardProductName : %s \n" \
|
||||
"boardSerialNumber : %s \n" \
|
||||
"boardPartNumber : %s \n" \
|
||||
"fruFileId : %s \n"
|
||||
|
||||
tmpstr = formatstr % (ord(self.boardversion), self.size,
|
||||
self.language, self.getMfgRealData(),
|
||||
self.boardManufacturer, self.boardProductName,
|
||||
self.boardSerialNumber, self.boardPartNumber,
|
||||
self.fruFileId)
|
||||
for i in range(1, 11):
|
||||
valtmp = "boardextra%d" % i
|
||||
if hasattr(self, valtmp):
|
||||
valtmpval = getattr(self, valtmp)
|
||||
tmpstr += "boardextra%d : %s \n" % (i, valtmpval)
|
||||
else:
|
||||
break
|
||||
|
||||
return tmpstr
|
||||
|
||||
def todict(self):
|
||||
dic = collections.OrderedDict()
|
||||
dic["boardversion"] = ord(self.boardversion)
|
||||
dic["boardlength"] = self.size
|
||||
dic["boardlanguage"] = self.language
|
||||
dic["boardmfg_date"] = self.getMfgRealData()
|
||||
dic["boardManufacturer"] = self.boardManufacturer
|
||||
dic["boardProductName"] = self.boardProductName
|
||||
dic["boardSerialNumber"] = self.boardSerialNumber
|
||||
dic["boardPartNumber"] = self.boardPartNumber
|
||||
dic["boardfruFileId"] = self.fruFileId
|
||||
for i in range(1, 11):
|
||||
valtmp = "boardextra%d" % i
|
||||
if hasattr(self, valtmp):
|
||||
valtmpval = getattr(self, valtmp)
|
||||
dic[valtmp] = valtmpval
|
||||
else:
|
||||
break
|
||||
return dic
|
||||
|
||||
def decodedata(self):
|
||||
index = 0
|
||||
self.areaversion = self.data[index]
|
||||
index += 1
|
||||
d_print("decode length :%d class size:%d" %
|
||||
((ord(self.data[index]) * 8), self.size))
|
||||
index += 2
|
||||
|
||||
timetmp = self.data[index: index + 3]
|
||||
self.mfg_date = ord(timetmp[0]) | (
|
||||
ord(timetmp[1]) << 8) | (ord(timetmp[2]) << 16)
|
||||
d_print("decode getMfgRealData :%s" % self.getMfgRealData())
|
||||
index += 3
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.boardManufacturer = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode boardManufacturer:%s" % self.boardManufacturer)
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.boardProductName = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode boardProductName:%s" % self.boardProductName)
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.boardSerialNumber = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode boardSerialNumber:%s" % self.boardSerialNumber)
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.boardPartNumber = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode boardPartNumber:%s" % self.boardPartNumber)
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.fruFileId = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode fruFileId:%s" % self.fruFileId)
|
||||
|
||||
|
||||
for i in range(1, 11):
|
||||
valtmp = "boardextra%d" % i
|
||||
if self.data[index] != chr(0xc1):
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
tmpval = self.data[index + 1: index + templen + 1]
|
||||
setattr(self, valtmp, tmpval)
|
||||
index += templen + 1
|
||||
d_print("decode boardextra%d:%s" % (i, tmpval))
|
||||
else:
|
||||
break
|
||||
|
||||
def recalcute(self):
|
||||
d_print("boardInfoArea version:%x" % ord(self.boardversion))
|
||||
d_print("boardInfoArea length:%d" % self.size)
|
||||
d_print("boardInfoArea language:%x" % self.language)
|
||||
self.mfg_date = FruUtil.minToData()
|
||||
d_print("boardInfoArea mfg_date:%x" % self.mfg_date)
|
||||
|
||||
self.data = chr(ord(self.boardversion)) + \
|
||||
chr(self.size / 8) + chr(self.language)
|
||||
|
||||
self.data += chr(self.mfg_date & 0xFF)
|
||||
self.data += chr((self.mfg_date >> 8) & 0xFF)
|
||||
self.data += chr((self.mfg_date >> 16) & 0xFF)
|
||||
|
||||
d_print("boardInfoArea boardManufacturer:%s" % self.boardManufacturer)
|
||||
typelength = FruUtil.getTypeLength(self.boardManufacturer)
|
||||
self.data += chr(typelength)
|
||||
self.data += self.boardManufacturer
|
||||
|
||||
d_print("boardInfoArea boardProductName:%s" % self.boardProductName)
|
||||
self.data += chr(FruUtil.getTypeLength(self.boardProductName))
|
||||
self.data += self.boardProductName
|
||||
|
||||
d_print("boardInfoArea boardSerialNumber:%s" % self.boardSerialNumber)
|
||||
self.data += chr(FruUtil.getTypeLength(self.boardSerialNumber))
|
||||
self.data += self.boardSerialNumber
|
||||
|
||||
d_print("boardInfoArea boardPartNumber:%s" % self.boardPartNumber)
|
||||
self.data += chr(FruUtil.getTypeLength(self.boardPartNumber))
|
||||
self.data += self.boardPartNumber
|
||||
|
||||
d_print("boardInfoArea fruFileId:%s" % self.fruFileId)
|
||||
self.data += chr(FruUtil.getTypeLength(self.fruFileId))
|
||||
self.data += self.fruFileId
|
||||
|
||||
for i in range(1, 11):
|
||||
valtmp = "boardextra%d" % i
|
||||
if hasattr(self, valtmp):
|
||||
valtmpval = getattr(self, valtmp)
|
||||
d_print("boardInfoArea boardextra%d:%s" % (i, valtmpval))
|
||||
self.data += chr(FruUtil.getTypeLength(valtmpval))
|
||||
if valtmpval is None:
|
||||
pass
|
||||
else:
|
||||
self.data += valtmpval
|
||||
else:
|
||||
break
|
||||
|
||||
self.data += chr(0xc1)
|
||||
|
||||
if len(self.data) > (self.size - 1):
|
||||
incr = (len(self.data) - self.size) / 8 + 1
|
||||
self.size += incr * 8
|
||||
|
||||
self.data = self.data[0:1] + chr(self.size / 8) + self.data[2:]
|
||||
d_print("self data:%d" % len(self.data))
|
||||
d_print("self size:%d" % self.size)
|
||||
d_print("adjust size:%d" % (self.size - len(self.data) - 1))
|
||||
self.data = self.data.ljust((self.size - 1), self.INITVALUE)
|
||||
|
||||
# checksum
|
||||
checksum = FruUtil.checksum(self.data)
|
||||
d_print("board info checksum:%x" % checksum)
|
||||
self.data += chr(checksum)
|
||||
|
||||
def getMfgRealData(self):
|
||||
starttime = datetime(1996, 1, 1, 0, 0, 0)
|
||||
mactime = starttime + timedelta(minutes=self.mfg_date)
|
||||
return mactime
|
||||
|
||||
@property
|
||||
def language(self):
|
||||
self._language = 25
|
||||
return self._language
|
||||
|
||||
@property
|
||||
def mfg_date(self):
|
||||
return self._mfg_date
|
||||
|
||||
@mfg_date.setter
|
||||
def mfg_date(self, val):
|
||||
self._mfg_date = val
|
||||
|
||||
@property
|
||||
def boardversion(self):
|
||||
self._boardversion = self.COMMON_HEAD_VERSION
|
||||
return self._boardversion
|
||||
|
||||
@property
|
||||
def fruFileId(self):
|
||||
return self._FRUFileID
|
||||
|
||||
@fruFileId.setter
|
||||
def fruFileId(self, val):
|
||||
self._FRUFileID = val
|
||||
|
||||
@property
|
||||
def boardPartNumber(self):
|
||||
return self._boardPartNumber
|
||||
|
||||
@boardPartNumber.setter
|
||||
def boardPartNumber(self, val):
|
||||
self._boardPartNumber = val
|
||||
|
||||
@property
|
||||
def boardSerialNumber(self):
|
||||
return self._boardSerialNumber
|
||||
|
||||
@boardSerialNumber.setter
|
||||
def boardSerialNumber(self, val):
|
||||
self._boardSerialNumber = val
|
||||
|
||||
@property
|
||||
def boardProductName(self):
|
||||
return self._boradProductName
|
||||
|
||||
@boardProductName.setter
|
||||
def boardProductName(self, val):
|
||||
self._boradProductName = val
|
||||
|
||||
@property
|
||||
def boardManufacturer(self):
|
||||
return self._boardManufacturer
|
||||
|
||||
@boardManufacturer.setter
|
||||
def boardManufacturer(self, val):
|
||||
self._boardManufacturer = val
|
||||
|
||||
@property
|
||||
def boardTime(self):
|
||||
return self._boardTime
|
||||
|
||||
@boardTime.setter
|
||||
def boardTime(self, val):
|
||||
self._boardTime = val
|
||||
|
||||
@property
|
||||
def fields(self):
|
||||
return self._fields
|
||||
|
||||
@fields.setter
|
||||
def fields(self, val):
|
||||
self._fields = val
|
||||
|
||||
|
||||
class ProductInfoArea(BaseArea):
|
||||
_productManufacturer = None
|
||||
_productAssetTag = None
|
||||
_FRUFileID = None
|
||||
|
||||
def __str__(self):
|
||||
formatstr = "version : %x\n" \
|
||||
"length : %d \n" \
|
||||
"language : %x \n" \
|
||||
"productManufacturer : %s \n" \
|
||||
"productName : %s \n" \
|
||||
"productPartModelName: %s \n" \
|
||||
"productVersion : %s \n" \
|
||||
"productSerialNumber : %s \n" \
|
||||
"productAssetTag : %s \n" \
|
||||
"fruFileId : %s \n"
|
||||
|
||||
tmpstr = formatstr % (ord(self.areaversion), self.size,
|
||||
self.language, self.productManufacturer,
|
||||
self.productName, self.productPartModelName,
|
||||
self.productVersion, self.productSerialNumber,
|
||||
self.productAssetTag, self.fruFileId)
|
||||
|
||||
for i in range(1, 11):
|
||||
valtmp = "productextra%d" % i
|
||||
if hasattr(self, valtmp):
|
||||
valtmpval = getattr(self, valtmp)
|
||||
tmpstr += "productextra%d : %s \n" % (i, valtmpval)
|
||||
else:
|
||||
break
|
||||
|
||||
return tmpstr
|
||||
|
||||
def todict(self):
|
||||
dic = collections.OrderedDict()
|
||||
dic["productversion"] = ord(self.areaversion)
|
||||
dic["productlength"] = self.size
|
||||
dic["productlanguage"] = self.language
|
||||
dic["productManufacturer"] = self.productManufacturer
|
||||
dic["productName"] = self.productName
|
||||
dic["productPartModelName"] = self.productPartModelName
|
||||
dic["productVersion"] = int(self.productVersion, 16)
|
||||
dic["productSerialNumber"] = self.productSerialNumber
|
||||
dic["productAssetTag"] = self.productAssetTag
|
||||
dic["productfruFileId"] = self.fruFileId
|
||||
for i in range(1, 11):
|
||||
valtmp = "productextra%d" % i
|
||||
if hasattr(self, valtmp):
|
||||
valtmpval = getattr(self, valtmp)
|
||||
dic[valtmp] = valtmpval
|
||||
else:
|
||||
break
|
||||
return dic
|
||||
|
||||
def decodedata(self):
|
||||
index = 0
|
||||
self.areaversion = self.data[index] # 0
|
||||
index += 1
|
||||
d_print("decode length %d" % (ord(self.data[index]) * 8))
|
||||
d_print("class size %d" % self.size)
|
||||
index += 2
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.productManufacturer = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode productManufacturer:%s" % self.productManufacturer)
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.productName = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode productName:%s" % self.productName)
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.productPartModelName = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode productPartModelName:%s" % self.productPartModelName)
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.productVersion = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode productVersion:%s" % self.productVersion)
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.productSerialNumber = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode productSerialNumber:%s" % self.productSerialNumber)
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.productAssetTag = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode productAssetTag:%s" % self.productAssetTag)
|
||||
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
self.fruFileId = self.data[index + 1: index + templen + 1]
|
||||
index += templen + 1
|
||||
d_print("decode fruFileId:%s" % self.fruFileId)
|
||||
|
||||
for i in range(1, 11):
|
||||
valtmp = "productextra%d" % i
|
||||
if self.data[index] != chr(0xc1) and index < self.size - 1:
|
||||
templen = FruUtil.decodeLength(self.data[index])
|
||||
if templen == 0:
|
||||
break
|
||||
tmpval = self.data[index + 1: index + templen + 1]
|
||||
d_print("decode boardextra%d:%s" % (i, tmpval))
|
||||
setattr(self, valtmp, tmpval)
|
||||
index += templen + 1
|
||||
else:
|
||||
break
|
||||
|
||||
@property
|
||||
def productVersion(self):
|
||||
return self._productVersion
|
||||
|
||||
@productVersion.setter
|
||||
def productVersion(self, name):
|
||||
self._productVersion = name
|
||||
|
||||
@property
|
||||
def areaversion(self):
|
||||
self._areaversion = self.COMMON_HEAD_VERSION
|
||||
return self._areaversion
|
||||
|
||||
@areaversion.setter
|
||||
def areaversion(self, name):
|
||||
self._areaversion = name
|
||||
|
||||
@property
|
||||
def language(self):
|
||||
self._language = 25
|
||||
return self._language
|
||||
|
||||
@property
|
||||
def productManufacturer(self):
|
||||
return self._productManufacturer
|
||||
|
||||
@productManufacturer.setter
|
||||
def productManufacturer(self, name):
|
||||
self._productManufacturer = name
|
||||
|
||||
@property
|
||||
def productName(self):
|
||||
return self._productName
|
||||
|
||||
@productName.setter
|
||||
def productName(self, name):
|
||||
self._productName = name
|
||||
|
||||
@property
|
||||
def productPartModelName(self):
|
||||
return self._productPartModelName
|
||||
|
||||
@productPartModelName.setter
|
||||
def productPartModelName(self, name):
|
||||
self._productPartModelName = name
|
||||
|
||||
@property
|
||||
def productSerialNumber(self):
|
||||
return self._productSerialNumber
|
||||
|
||||
@productSerialNumber.setter
|
||||
def productSerialNumber(self, name):
|
||||
self._productSerialNumber = name
|
||||
|
||||
@property
|
||||
def productAssetTag(self):
|
||||
return self._productAssetTag
|
||||
|
||||
@productAssetTag.setter
|
||||
def productAssetTag(self, name):
|
||||
self._productAssetTag = name
|
||||
|
||||
@property
|
||||
def fruFileId(self):
|
||||
return self._FRUFileID
|
||||
|
||||
@fruFileId.setter
|
||||
def fruFileId(self, name):
|
||||
self._FRUFileID = name
|
||||
|
||||
def recalcute(self):
|
||||
d_print("product version:%x" % ord(self.areaversion))
|
||||
d_print("product length:%d" % self.size)
|
||||
d_print("product language:%x" % self.language)
|
||||
self.data = chr(ord(self.areaversion)) + \
|
||||
chr(self.size / 8) + chr(self.language)
|
||||
|
||||
typelength = FruUtil.getTypeLength(self.productManufacturer)
|
||||
self.data += chr(typelength)
|
||||
self.data += self.productManufacturer
|
||||
|
||||
self.data += chr(FruUtil.getTypeLength(self.productName))
|
||||
self.data += self.productName
|
||||
|
||||
self.data += chr(FruUtil.getTypeLength(self.productPartModelName))
|
||||
self.data += self.productPartModelName
|
||||
|
||||
self.data += chr(FruUtil.getTypeLength(self.productVersion))
|
||||
self.data += self.productVersion
|
||||
|
||||
self.data += chr(FruUtil.getTypeLength(self.productSerialNumber))
|
||||
self.data += self.productSerialNumber
|
||||
|
||||
self.data += chr(FruUtil.getTypeLength(self.productAssetTag))
|
||||
if self.productAssetTag is not None:
|
||||
self.data += self.productAssetTag
|
||||
|
||||
self.data += chr(FruUtil.getTypeLength(self.fruFileId))
|
||||
self.data += self.fruFileId
|
||||
|
||||
# whether the extended field exists or not
|
||||
for i in range(1, 11):
|
||||
valtmp = "productextra%d" % i
|
||||
if hasattr(self, valtmp):
|
||||
valtmpval = getattr(self, valtmp)
|
||||
d_print("boardInfoArea productextra%d:%s" % (i, valtmpval))
|
||||
self.data += chr(FruUtil.getTypeLength(valtmpval))
|
||||
if valtmpval is None:
|
||||
pass
|
||||
else:
|
||||
self.data += valtmpval
|
||||
else:
|
||||
break
|
||||
|
||||
self.data += chr(0xc1)
|
||||
if len(self.data) > (self.size - 1):
|
||||
incr = (len(self.data) - self.size) / 8 + 1
|
||||
self.size += incr * 8
|
||||
d_print("self.data:%d" % len(self.data))
|
||||
d_print("self.size:%d" % self.size)
|
||||
|
||||
self.data = self.data[0:1] + chr(self.size / 8) + self.data[2:]
|
||||
self.data = self.data.ljust((self.size - 1), self.INITVALUE)
|
||||
checksum = FruUtil.checksum(self.data)
|
||||
d_print("board info checksum:%x" % checksum)
|
||||
self.data += chr(checksum)
|
||||
|
||||
|
||||
class MultiRecordArea(BaseArea):
|
||||
pass
|
||||
|
||||
|
||||
class Field(object):
|
||||
|
||||
def __init__(self, fieldType="ASCII", fieldData=""):
|
||||
self.fieldData = fieldData
|
||||
self.fieldType = fieldType
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def fieldType(self):
|
||||
return self._fieldType
|
||||
|
||||
@property
|
||||
def fieldData(self):
|
||||
return self._fieldData
|
||||
|
||||
|
||||
class ipmifru(BaseArea):
|
||||
_BoardInfoArea = None
|
||||
_ProductInfoArea = None
|
||||
_InternalUseArea = None
|
||||
_ChassisInfoArea = None
|
||||
_multiRecordArea = None
|
||||
_productinfoAreaOffset = BaseArea.INITVALUE
|
||||
_boardInfoAreaOffset = BaseArea.INITVALUE
|
||||
_internalUserAreaOffset = BaseArea.INITVALUE
|
||||
_chassicInfoAreaOffset = BaseArea.INITVALUE
|
||||
_multiRecordAreaOffset = BaseArea.INITVALUE
|
||||
_bindata = None
|
||||
_bodybin = None
|
||||
_version = BaseArea.COMMON_HEAD_VERSION
|
||||
_zeroCheckSum = None
|
||||
_frusize = 256
|
||||
|
||||
def __str__(self):
|
||||
tmpstr = ""
|
||||
if self.boardInfoArea.isPresent:
|
||||
tmpstr += "\nboardinfoarea: \n"
|
||||
tmpstr += self.boardInfoArea.__str__()
|
||||
if self.productInfoArea.isPresent:
|
||||
tmpstr += "\nproductinfoarea: \n"
|
||||
tmpstr += self.productInfoArea.__str__()
|
||||
return tmpstr
|
||||
|
||||
def decodeBin(self, eeprom):
|
||||
commonHead = eeprom[0:8]
|
||||
d_print("decode version %x" % ord(commonHead[0]))
|
||||
if self.COMMON_HEAD_VERSION != commonHead[0]:
|
||||
raise FruException("HEAD VERSION error,not Fru format!", -10)
|
||||
if FruUtil.checksum(commonHead[0:7]) != ord(commonHead[7]):
|
||||
strtemp = "check header checksum error [cal:%02x data:%02x]" % (
|
||||
FruUtil.checksum(commonHead[0:7]), ord(commonHead[7]))
|
||||
raise FruException(strtemp, -3)
|
||||
if commonHead[1] != self.INITVALUE:
|
||||
d_print("Internal Use Area is present")
|
||||
self.internalUseArea = InternalUseArea(
|
||||
name="Internal Use Area", size=self.SUGGESTED_SIZE_INTERNAL_USE_AREA)
|
||||
self.internalUseArea.isPresent = True
|
||||
self.internalUserAreaOffset = ord(commonHead[1])
|
||||
self.internalUseArea.data = eeprom[self.internalUserAreaOffset * 8: (
|
||||
self.internalUserAreaOffset * 8 + self.internalUseArea.size)]
|
||||
if commonHead[2] != self.INITVALUE:
|
||||
d_print("Chassis Info Area is present")
|
||||
self.chassisInfoArea = ChassisInfoArea(
|
||||
name="Chassis Info Area", size=self.SUGGESTED_SIZE_CHASSIS_INFO_AREA)
|
||||
self.chassisInfoArea.isPresent = True
|
||||
self.chassicInfoAreaOffset = ord(commonHead[2])
|
||||
self.chassisInfoArea.data = eeprom[self.chassicInfoAreaOffset * 8: (
|
||||
self.chassicInfoAreaOffset * 8 + self.chassisInfoArea.size)]
|
||||
if commonHead[3] != self.INITVALUE:
|
||||
self.boardInfoArea = BoardInfoArea(
|
||||
name="Board Info Area", size=self.SUGGESTED_SIZE_BOARD_INFO_AREA)
|
||||
self.boardInfoArea.isPresent = True
|
||||
self.boardInfoAreaOffset = ord(commonHead[3])
|
||||
self.boardInfoArea.size = ord(
|
||||
eeprom[self.boardInfoAreaOffset * 8 + 1]) * 8
|
||||
d_print("Board Info Area is present size:%d" %
|
||||
(self.boardInfoArea.size))
|
||||
self.boardInfoArea.data = eeprom[self.boardInfoAreaOffset * 8: (
|
||||
self.boardInfoAreaOffset * 8 + self.boardInfoArea.size)]
|
||||
if FruUtil.checksum(self.boardInfoArea.data[:-1]) != ord(self.boardInfoArea.data[-1:]):
|
||||
strtmp = "check boardInfoArea checksum error[cal:%02x data:%02x]" % \
|
||||
(FruUtil.checksum(
|
||||
self.boardInfoArea.data[:-1]), ord(self.boardInfoArea.data[-1:]))
|
||||
raise FruException(strtmp, -3)
|
||||
self.boardInfoArea.decodedata()
|
||||
if commonHead[4] != self.INITVALUE:
|
||||
d_print("Product Info Area is present")
|
||||
self.productInfoArea = ProductInfoArea(
|
||||
name="Product Info Area ", size=self.SUGGESTED_SIZE_PRODUCT_INFO_AREA)
|
||||
self.productInfoArea.isPresent = True
|
||||
self.productinfoAreaOffset = ord(commonHead[4])
|
||||
d_print("length offset value: %02x" %
|
||||
ord(eeprom[self.productinfoAreaOffset * 8 + 1]))
|
||||
self.productInfoArea.size = ord(
|
||||
eeprom[self.productinfoAreaOffset * 8 + 1]) * 8
|
||||
d_print("Product Info Area is present size:%d" %
|
||||
(self.productInfoArea.size))
|
||||
|
||||
self.productInfoArea.data = eeprom[self.productinfoAreaOffset * 8: (
|
||||
self.productinfoAreaOffset * 8 + self.productInfoArea.size)]
|
||||
if FruUtil.checksum(self.productInfoArea.data[:-1]) != ord(self.productInfoArea.data[-1:]):
|
||||
strtmp = "check productInfoArea checksum error [cal:%02x data:%02x]" % (
|
||||
FruUtil.checksum(self.productInfoArea.data[:-1]), ord(self.productInfoArea.data[-1:]))
|
||||
raise FruException(strtmp, -3)
|
||||
self.productInfoArea.decodedata()
|
||||
if commonHead[5] != self.INITVALUE:
|
||||
self.multiRecordArea = MultiRecordArea(
|
||||
name="MultiRecord record Area ")
|
||||
d_print("MultiRecord record present")
|
||||
self.multiRecordArea.isPresent = True
|
||||
self.multiRecordAreaOffset = ord(commonHead[5])
|
||||
self.multiRecordArea.data = eeprom[self.multiRecordAreaOffset * 8: (
|
||||
self.multiRecordAreaOffset * 8 + self.multiRecordArea.size)]
|
||||
|
||||
def initDefault(self):
|
||||
self.version = self.COMMON_HEAD_VERSION
|
||||
self.internalUserAreaOffset = self.INITVALUE
|
||||
self.chassicInfoAreaOffset = self.INITVALUE
|
||||
self.boardInfoAreaOffset = self.INITVALUE
|
||||
self.productinfoAreaOffset = self.INITVALUE
|
||||
self.multiRecordAreaOffset = self.INITVALUE
|
||||
self.PAD = self.INITVALUE
|
||||
self.zeroCheckSum = self.INITVALUE
|
||||
self.offset = self.SUGGESTED_SIZE_COMMON_HEADER
|
||||
self.productInfoArea = None
|
||||
self.internalUseArea = None
|
||||
self.boardInfoArea = None
|
||||
self.chassisInfoArea = None
|
||||
self.multiRecordArea = None
|
||||
# self.recalcute()
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
return self._version
|
||||
|
||||
@version.setter
|
||||
def version(self, name):
|
||||
self._version = name
|
||||
|
||||
@property
|
||||
def internalUserAreaOffset(self):
|
||||
return self._internalUserAreaOffset
|
||||
|
||||
@internalUserAreaOffset.setter
|
||||
def internalUserAreaOffset(self, obj):
|
||||
self._internalUserAreaOffset = obj
|
||||
|
||||
@property
|
||||
def chassicInfoAreaOffset(self):
|
||||
return self._chassicInfoAreaOffset
|
||||
|
||||
@chassicInfoAreaOffset.setter
|
||||
def chassicInfoAreaOffset(self, obj):
|
||||
self._chassicInfoAreaOffset = obj
|
||||
|
||||
@property
|
||||
def productinfoAreaOffset(self):
|
||||
return self._productinfoAreaOffset
|
||||
|
||||
@productinfoAreaOffset.setter
|
||||
def productinfoAreaOffset(self, obj):
|
||||
self._productinfoAreaOffset = obj
|
||||
|
||||
@property
|
||||
def boardInfoAreaOffset(self):
|
||||
return self._boardInfoAreaOffset
|
||||
|
||||
@boardInfoAreaOffset.setter
|
||||
def boardInfoAreaOffset(self, obj):
|
||||
self._boardInfoAreaOffset = obj
|
||||
|
||||
@property
|
||||
def multiRecordAreaOffset(self):
|
||||
return self._multiRecordAreaOffset
|
||||
|
||||
@multiRecordAreaOffset.setter
|
||||
def multiRecordAreaOffset(self, obj):
|
||||
self._multiRecordAreaOffset = obj
|
||||
|
||||
@property
|
||||
def zeroCheckSum(self):
|
||||
return self._zeroCheckSum
|
||||
|
||||
@zeroCheckSum.setter
|
||||
def zeroCheckSum(self, obj):
|
||||
self._zeroCheckSum = obj
|
||||
|
||||
@property
|
||||
def productInfoArea(self):
|
||||
return self._ProductInfoArea
|
||||
|
||||
@productInfoArea.setter
|
||||
def productInfoArea(self, obj):
|
||||
self._ProductInfoArea = obj
|
||||
|
||||
@property
|
||||
def internalUseArea(self):
|
||||
return self._InternalUseArea
|
||||
|
||||
@internalUseArea.setter
|
||||
def internalUseArea(self, obj):
|
||||
self.internalUseArea = obj
|
||||
|
||||
@property
|
||||
def boardInfoArea(self):
|
||||
return self._BoardInfoArea
|
||||
|
||||
@boardInfoArea.setter
|
||||
def boardInfoArea(self, obj):
|
||||
self._BoardInfoArea = obj
|
||||
|
||||
@property
|
||||
def chassisInfoArea(self):
|
||||
return self._ChassisInfoArea
|
||||
|
||||
@chassisInfoArea.setter
|
||||
def chassisInfoArea(self, obj):
|
||||
self._ChassisInfoArea = obj
|
||||
|
||||
@property
|
||||
def multiRecordArea(self):
|
||||
return self._multiRecordArea
|
||||
|
||||
@multiRecordArea.setter
|
||||
def multiRecordArea(self, obj):
|
||||
self._multiRecordArea = obj
|
||||
|
||||
@property
|
||||
def bindata(self):
|
||||
return self._bindata
|
||||
|
||||
@bindata.setter
|
||||
def bindata(self, obj):
|
||||
self._bindata = obj
|
||||
|
||||
@property
|
||||
def bodybin(self):
|
||||
return self._bodybin
|
||||
|
||||
@bodybin.setter
|
||||
def bodybin(self, obj):
|
||||
self._bodybin = obj
|
||||
|
||||
def recalcuteCommonHead(self):
|
||||
self.bindata = ""
|
||||
self.offset = self.SUGGESTED_SIZE_COMMON_HEADER
|
||||
d_print("common Header %d" % self.offset)
|
||||
d_print("fru eeprom size %d" % self._frusize)
|
||||
if self.internalUseArea is not None and self.internalUseArea.isPresent:
|
||||
self.internalUserAreaOffset = self.offset / 8
|
||||
self.offset += self.internalUseArea.size
|
||||
d_print("internalUseArea is present offset:%d" % self.offset)
|
||||
|
||||
if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent:
|
||||
self.chassicInfoAreaOffset = self.offset / 8
|
||||
self.offset += self.chassisInfoArea.size
|
||||
d_print("chassisInfoArea is present offset:%d" % self.offset)
|
||||
|
||||
if self.boardInfoArea is not None and self.boardInfoArea.isPresent:
|
||||
self.boardInfoAreaOffset = self.offset / 8
|
||||
self.offset += self.boardInfoArea.size
|
||||
d_print("boardInfoArea is present offset:%d" % self.offset)
|
||||
d_print("boardInfoArea is present size:%d" %
|
||||
self.boardInfoArea.size)
|
||||
|
||||
if self.productInfoArea is not None and self.productInfoArea.isPresent:
|
||||
self.productinfoAreaOffset = self.offset / 8
|
||||
self.offset += self.productInfoArea.size
|
||||
d_print("productInfoArea is present offset:%d" % self.offset)
|
||||
|
||||
if self.multiRecordArea is not None and self.multiRecordArea.isPresent:
|
||||
self.multiRecordAreaOffset = self.offset / 8
|
||||
d_print("multiRecordArea is present offset:%d" % self.offset)
|
||||
|
||||
if self.internalUserAreaOffset == self.INITVALUE:
|
||||
self.internalUserAreaOffset = 0
|
||||
if self.productinfoAreaOffset == self.INITVALUE:
|
||||
self.productinfoAreaOffset = 0
|
||||
if self.chassicInfoAreaOffset == self.INITVALUE:
|
||||
self.chassicInfoAreaOffset = 0
|
||||
if self.boardInfoAreaOffset == self.INITVALUE:
|
||||
self.boardInfoAreaOffset = 0
|
||||
if self.multiRecordAreaOffset == self.INITVALUE:
|
||||
self.multiRecordAreaOffset = 0
|
||||
|
||||
self.zeroCheckSum = (0x100 - ord(self.version) - self.internalUserAreaOffset - self.chassicInfoAreaOffset - self.productinfoAreaOffset
|
||||
- self.boardInfoAreaOffset - self.multiRecordAreaOffset) & 0xff
|
||||
d_print("zerochecksum:%x" % self.zeroCheckSum)
|
||||
self.data = self.version + chr(self.internalUserAreaOffset) + chr(self.chassicInfoAreaOffset) + chr(
|
||||
self.boardInfoAreaOffset) + chr(self.productinfoAreaOffset) + chr(self.multiRecordAreaOffset) + self.INITVALUE + chr(self.zeroCheckSum)
|
||||
|
||||
self.bindata = self.data + self.bodybin
|
||||
totallen = len(self.bindata)
|
||||
d_print("totallen %d" % totallen)
|
||||
if (totallen < self._frusize):
|
||||
self.bindata = self.bindata.ljust(self._frusize, self.INITVALUE)
|
||||
else:
|
||||
raise FruException('bin data more than %d' % self._frusize, -2)
|
||||
|
||||
def recalcutebin(self):
|
||||
self.bodybin = ""
|
||||
if self.internalUseArea is not None and self.internalUseArea.isPresent:
|
||||
d_print("internalUseArea present")
|
||||
self.bodybin += self.internalUseArea.data
|
||||
if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent:
|
||||
d_print("chassisInfoArea present")
|
||||
self.bodybin += self.chassisInfoArea.data
|
||||
if self.boardInfoArea is not None and self.boardInfoArea.isPresent:
|
||||
d_print("boardInfoArea present")
|
||||
self.boardInfoArea.recalcute()
|
||||
self.bodybin += self.boardInfoArea.data
|
||||
if self.productInfoArea is not None and self.productInfoArea.isPresent:
|
||||
d_print("productInfoAreapresent")
|
||||
self.productInfoArea.recalcute()
|
||||
self.bodybin += self.productInfoArea.data
|
||||
if self.multiRecordArea is not None and self.multiRecordArea.isPresent:
|
||||
d_print("multiRecordArea present")
|
||||
self.bodybin += self.productInfoArea.data
|
||||
|
||||
def recalcute(self, fru_eeprom_size = 256):
|
||||
self._frusize = fru_eeprom_size
|
||||
self.recalcutebin()
|
||||
self.recalcuteCommonHead()
|
@ -1,23 +0,0 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
import os
|
||||
|
||||
def get_machine_info():
|
||||
if not os.path.isfile('/host/machine.conf'):
|
||||
return None
|
||||
machine_vars = {}
|
||||
with open('/host/machine.conf') as machine_file:
|
||||
for line in machine_file:
|
||||
tokens = line.split('=')
|
||||
if len(tokens) < 2:
|
||||
continue
|
||||
machine_vars[tokens[0]] = tokens[1].strip()
|
||||
return machine_vars
|
||||
|
||||
def get_platform_info(machine_info):
|
||||
if machine_info != None:
|
||||
if 'onie_platform' in machine_info:
|
||||
return machine_info['onie_platform']
|
||||
elif 'aboot_platform' in machine_info:
|
||||
return machine_info['aboot_platform']
|
||||
return None
|
||||
|
@ -1,67 +0,0 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
import logging
|
||||
from syslog import (
|
||||
syslog,
|
||||
openlog,
|
||||
LOG_WARNING,
|
||||
LOG_CRIT,
|
||||
LOG_DEBUG,
|
||||
LOG_ERR,
|
||||
LOG_PID,
|
||||
LOG_INFO,
|
||||
)
|
||||
|
||||
class Logger():
|
||||
def __init__(self, prefix, filepath=None, syslog=False, dbg_mask=0x0):
|
||||
self.logger = None
|
||||
if syslog is False:
|
||||
if filepath is None:
|
||||
raise AttributeError("filepath needed")
|
||||
|
||||
# init logging
|
||||
formatter = logging.Formatter( "%(asctime)s %(levelname)s %(filename)s[%(funcName)s][%(lineno)s]: %(message)s")
|
||||
handler = logging.FileHandler(self.filepath)
|
||||
handler.setFormatter(formatter)
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
self.logger.addHandler(handler)
|
||||
|
||||
self.prefix = prefix
|
||||
self.use_syslog = syslog
|
||||
self.dbg_mask = dbg_mask
|
||||
|
||||
def info(self, s):
|
||||
if self.use_syslog:
|
||||
self._syslog(s, LOG_INFO)
|
||||
else:
|
||||
self.logger.info(s)
|
||||
|
||||
def debug(self, dbg_lvl, s):
|
||||
if dbg_lvl & self.dbg_mask:
|
||||
if self.use_syslog:
|
||||
self._syslog(s, LOG_DEBUG)
|
||||
else:
|
||||
self.logger.debug(s)
|
||||
|
||||
def warn(self, s):
|
||||
if self.use_syslog:
|
||||
self._syslog(s, LOG_WARNING)
|
||||
else:
|
||||
self.logger.warning(s)
|
||||
|
||||
def error(self, s):
|
||||
if self.use_syslog:
|
||||
self._syslog(s, LOG_ERR)
|
||||
else:
|
||||
self.logger.error(s)
|
||||
|
||||
def crit(self, s):
|
||||
if self.use_syslog:
|
||||
self._syslog(s, LOG_CRIT)
|
||||
else:
|
||||
self.logger.critical(s)
|
||||
|
||||
def _syslog(self, s, t):
|
||||
openlog(self.prefix, LOG_PID)
|
||||
syslog(t, s)
|
@ -1,774 +0,0 @@
|
||||
"""smbus2 - A drop-in replacement for smbus-cffi/smbus-python"""
|
||||
# The MIT License (MIT)
|
||||
# Copyright (c) 2017 Karl-Petter Lindegaard
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import os
|
||||
import sys
|
||||
from fcntl import ioctl
|
||||
from ctypes import c_uint32, c_uint8, c_uint16, c_char, POINTER, Structure, Array, Union, create_string_buffer, string_at
|
||||
|
||||
|
||||
# Commands from uapi/linux/i2c-dev.h
|
||||
I2C_SLAVE = 0x0703 # Use this slave address
|
||||
I2C_SLAVE_FORCE = 0x0706 # Use this slave address, even if it is already in use by a driver!
|
||||
I2C_FUNCS = 0x0705 # Get the adapter functionality mask
|
||||
I2C_RDWR = 0x0707 # Combined R/W transfer (one STOP only)
|
||||
I2C_SMBUS = 0x0720 # SMBus transfer. Takes pointer to i2c_smbus_ioctl_data
|
||||
I2C_PEC = 0x0708
|
||||
|
||||
# SMBus transfer read or write markers from uapi/linux/i2c.h
|
||||
I2C_SMBUS_WRITE = 0
|
||||
I2C_SMBUS_READ = 1
|
||||
|
||||
# Size identifiers uapi/linux/i2c.h
|
||||
I2C_SMBUS_QUICK = 0
|
||||
I2C_SMBUS_BYTE = 1
|
||||
I2C_SMBUS_BYTE_DATA = 2
|
||||
I2C_SMBUS_WORD_DATA = 3
|
||||
I2C_SMBUS_PROC_CALL = 4
|
||||
I2C_SMBUS_BLOCK_DATA = 5 # This isn't supported by Pure-I2C drivers with SMBUS emulation, like those in RaspberryPi, OrangePi, etc :(
|
||||
I2C_SMBUS_BLOCK_PROC_CALL = 7 # Like I2C_SMBUS_BLOCK_DATA, it isn't supported by Pure-I2C drivers either.
|
||||
I2C_SMBUS_I2C_BLOCK_DATA = 8
|
||||
I2C_SMBUS_BLOCK_MAX = 32
|
||||
|
||||
# To determine what functionality is present (uapi/linux/i2c.h)
|
||||
try:
|
||||
from enum import IntFlag
|
||||
except ImportError:
|
||||
IntFlag = int
|
||||
|
||||
|
||||
class I2cFunc(IntFlag):
|
||||
"""
|
||||
These flags identify the operations supported by an I2C/SMBus device.
|
||||
|
||||
You can test these flags on your `smbus.funcs`
|
||||
|
||||
On newer python versions, I2cFunc is an IntFlag enum, but it
|
||||
falls back to class with a bunch of int constants on older releases.
|
||||
"""
|
||||
I2C = 0x00000001
|
||||
ADDR_10BIT = 0x00000002
|
||||
PROTOCOL_MANGLING = 0x00000004 # I2C_M_IGNORE_NAK etc.
|
||||
SMBUS_PEC = 0x00000008
|
||||
NOSTART = 0x00000010 # I2C_M_NOSTART
|
||||
SLAVE = 0x00000020
|
||||
SMBUS_BLOCK_PROC_CALL = 0x00008000 # SMBus 2.0
|
||||
SMBUS_QUICK = 0x00010000
|
||||
SMBUS_READ_BYTE = 0x00020000
|
||||
SMBUS_WRITE_BYTE = 0x00040000
|
||||
SMBUS_READ_BYTE_DATA = 0x00080000
|
||||
SMBUS_WRITE_BYTE_DATA = 0x00100000
|
||||
SMBUS_READ_WORD_DATA = 0x00200000
|
||||
SMBUS_WRITE_WORD_DATA = 0x00400000
|
||||
SMBUS_PROC_CALL = 0x00800000
|
||||
SMBUS_READ_BLOCK_DATA = 0x01000000
|
||||
SMBUS_WRITE_BLOCK_DATA = 0x02000000
|
||||
SMBUS_READ_I2C_BLOCK = 0x04000000 # I2C-like block xfer
|
||||
SMBUS_WRITE_I2C_BLOCK = 0x08000000 # w/ 1-byte reg. addr.
|
||||
SMBUS_HOST_NOTIFY = 0x10000000
|
||||
|
||||
SMBUS_BYTE = 0x00060000
|
||||
SMBUS_BYTE_DATA = 0x00180000
|
||||
SMBUS_WORD_DATA = 0x00600000
|
||||
SMBUS_BLOCK_DATA = 0x03000000
|
||||
SMBUS_I2C_BLOCK = 0x0c000000
|
||||
SMBUS_EMUL = 0x0eff0008
|
||||
|
||||
|
||||
# i2c_msg flags from uapi/linux/i2c.h
|
||||
I2C_M_RD = 0x0001
|
||||
|
||||
# Pointer definitions
|
||||
LP_c_uint8 = POINTER(c_uint8)
|
||||
LP_c_uint16 = POINTER(c_uint16)
|
||||
LP_c_uint32 = POINTER(c_uint32)
|
||||
|
||||
|
||||
#############################################################
|
||||
# Type definitions as in i2c.h
|
||||
|
||||
|
||||
class i2c_smbus_data(Array):
|
||||
"""
|
||||
Adaptation of the i2c_smbus_data union in ``i2c.h``.
|
||||
|
||||
Data for SMBus messages.
|
||||
"""
|
||||
_length_ = I2C_SMBUS_BLOCK_MAX + 2
|
||||
_type_ = c_uint8
|
||||
|
||||
|
||||
class union_i2c_smbus_data(Union):
|
||||
_fields_ = [
|
||||
("byte", c_uint8),
|
||||
("word", c_uint16),
|
||||
("block", i2c_smbus_data)
|
||||
]
|
||||
|
||||
|
||||
union_pointer_type = POINTER(union_i2c_smbus_data)
|
||||
|
||||
|
||||
class i2c_smbus_ioctl_data(Structure):
|
||||
"""
|
||||
As defined in ``i2c-dev.h``.
|
||||
"""
|
||||
_fields_ = [
|
||||
('read_write', c_uint8),
|
||||
('command', c_uint8),
|
||||
('size', c_uint32),
|
||||
('data', union_pointer_type)]
|
||||
__slots__ = [name for name, type in _fields_]
|
||||
|
||||
@staticmethod
|
||||
def create(read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE_DATA):
|
||||
u = union_i2c_smbus_data()
|
||||
return i2c_smbus_ioctl_data(
|
||||
read_write=read_write, command=command, size=size,
|
||||
data=union_pointer_type(u))
|
||||
|
||||
|
||||
#############################################################
|
||||
# Type definitions for i2c_rdwr combined transactions
|
||||
|
||||
|
||||
class i2c_msg(Structure):
|
||||
"""
|
||||
As defined in ``i2c.h``.
|
||||
"""
|
||||
_fields_ = [
|
||||
('addr', c_uint16),
|
||||
('flags', c_uint16),
|
||||
('len', c_uint16),
|
||||
('buf', POINTER(c_char))]
|
||||
|
||||
def __iter__(self):
|
||||
""" Iterator / Generator
|
||||
|
||||
:return: iterates over :py:attr:`buf`
|
||||
:rtype: :py:class:`generator` which returns int values
|
||||
"""
|
||||
idx = 0
|
||||
while idx < self.len:
|
||||
yield ord(self.buf[idx])
|
||||
idx += 1
|
||||
|
||||
def __len__(self):
|
||||
return self.len
|
||||
|
||||
def __bytes__(self):
|
||||
return string_at(self.buf, self.len)
|
||||
|
||||
def __repr__(self):
|
||||
return 'i2c_msg(%d,%d,%r)' % (self.addr, self.flags, self.__bytes__())
|
||||
|
||||
def __str__(self):
|
||||
s = self.__bytes__()
|
||||
if sys.version_info.major >= 3:
|
||||
s = ''.join(map(chr, s))
|
||||
return s
|
||||
|
||||
@staticmethod
|
||||
def read(address, length):
|
||||
"""
|
||||
Prepares an i2c read transaction.
|
||||
|
||||
:param address: Slave address.
|
||||
:type: address: int
|
||||
:param length: Number of bytes to read.
|
||||
:type: length: int
|
||||
:return: New :py:class:`i2c_msg` instance for read operation.
|
||||
:rtype: :py:class:`i2c_msg`
|
||||
"""
|
||||
arr = create_string_buffer(length)
|
||||
return i2c_msg(
|
||||
addr=address, flags=I2C_M_RD, len=length,
|
||||
buf=arr)
|
||||
|
||||
@staticmethod
|
||||
def write(address, buf):
|
||||
"""
|
||||
Prepares an i2c write transaction.
|
||||
|
||||
:param address: Slave address.
|
||||
:type address: int
|
||||
:param buf: Bytes to write. Either list of values or str.
|
||||
:type buf: list
|
||||
:return: New :py:class:`i2c_msg` instance for write operation.
|
||||
:rtype: :py:class:`i2c_msg`
|
||||
"""
|
||||
if sys.version_info.major >= 3:
|
||||
if type(buf) is str:
|
||||
buf = bytes(map(ord, buf))
|
||||
else:
|
||||
buf = bytes(buf)
|
||||
else:
|
||||
if type(buf) is not str:
|
||||
buf = ''.join([chr(x) for x in buf])
|
||||
arr = create_string_buffer(buf, len(buf))
|
||||
return i2c_msg(
|
||||
addr=address, flags=0, len=len(arr),
|
||||
buf=arr)
|
||||
|
||||
|
||||
class i2c_rdwr_ioctl_data(Structure):
|
||||
"""
|
||||
As defined in ``i2c-dev.h``.
|
||||
"""
|
||||
_fields_ = [
|
||||
('msgs', POINTER(i2c_msg)),
|
||||
('nmsgs', c_uint32)
|
||||
]
|
||||
__slots__ = [name for name, type in _fields_]
|
||||
|
||||
@staticmethod
|
||||
def create(*i2c_msg_instances):
|
||||
"""
|
||||
Factory method for creating a i2c_rdwr_ioctl_data struct that can
|
||||
be called with ``ioctl(fd, I2C_RDWR, data)``.
|
||||
|
||||
:param i2c_msg_instances: Up to 42 i2c_msg instances
|
||||
:rtype: i2c_rdwr_ioctl_data
|
||||
"""
|
||||
n_msg = len(i2c_msg_instances)
|
||||
msg_array = (i2c_msg * n_msg)(*i2c_msg_instances)
|
||||
return i2c_rdwr_ioctl_data(
|
||||
msgs=msg_array,
|
||||
nmsgs=n_msg
|
||||
)
|
||||
|
||||
|
||||
#############################################################
|
||||
|
||||
|
||||
class SMBus(object):
|
||||
|
||||
def __init__(self, bus=None, force=False):
|
||||
"""
|
||||
Initialize and (optionally) open an i2c bus connection.
|
||||
|
||||
:param bus: i2c bus number (e.g. 0 or 1)
|
||||
or an absolute file path (e.g. `/dev/i2c-42`).
|
||||
If not given, a subsequent call to ``open()`` is required.
|
||||
:type bus: int or str
|
||||
:param force: force using the slave address even when driver is
|
||||
already using it.
|
||||
:type force: boolean
|
||||
"""
|
||||
self.fd = None
|
||||
self.funcs = I2cFunc(0)
|
||||
if bus is not None:
|
||||
self.open(bus)
|
||||
self.address = None
|
||||
self.force = force
|
||||
self._force_last = None
|
||||
|
||||
def __enter__(self):
|
||||
"""Enter handler."""
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
"""Exit handler."""
|
||||
self.close()
|
||||
|
||||
def open(self, bus):
|
||||
"""
|
||||
Open a given i2c bus.
|
||||
|
||||
:param bus: i2c bus number (e.g. 0 or 1)
|
||||
or an absolute file path (e.g. '/dev/i2c-42').
|
||||
:type bus: int or str
|
||||
:raise TypeError: if type(bus) is not in (int, str)
|
||||
"""
|
||||
if isinstance(bus, int):
|
||||
filepath = "/dev/i2c-{}".format(bus)
|
||||
elif isinstance(bus, str):
|
||||
filepath = bus
|
||||
else:
|
||||
raise TypeError("Unexpected type(bus)={}".format(type(bus)))
|
||||
|
||||
self.fd = os.open(filepath, os.O_RDWR)
|
||||
self.funcs = self._get_funcs()
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Close the i2c connection.
|
||||
"""
|
||||
if self.fd:
|
||||
os.close(self.fd)
|
||||
self.fd = None
|
||||
|
||||
def _set_address(self, address, force=None):
|
||||
"""
|
||||
Set i2c slave address to use for subsequent calls.
|
||||
|
||||
:param address:
|
||||
:type address: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
"""
|
||||
force = force if force is not None else self.force
|
||||
if self.address != address or self._force_last != force:
|
||||
if force is True:
|
||||
ioctl(self.fd, I2C_SLAVE_FORCE, address)
|
||||
else:
|
||||
ioctl(self.fd, I2C_SLAVE, address)
|
||||
self.address = address
|
||||
self._force_last = force
|
||||
|
||||
def _get_funcs(self):
|
||||
"""
|
||||
Returns a 32-bit value stating supported I2C functions.
|
||||
|
||||
:rtype: int
|
||||
"""
|
||||
f = c_uint32()
|
||||
ioctl(self.fd, I2C_FUNCS, f)
|
||||
return f.value
|
||||
|
||||
def write_quick(self, i2c_addr, force=None):
|
||||
"""
|
||||
Perform quick transaction. Throws IOError if unsuccessful.
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
"""
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_WRITE, command=0, size=I2C_SMBUS_QUICK)
|
||||
ioctl(self.fd, I2C_SMBUS, msg)
|
||||
|
||||
def read_byte(self, i2c_addr, force=None):
|
||||
"""
|
||||
Read a single byte from a device.
|
||||
|
||||
:rtype: int
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:return: Read byte value
|
||||
"""
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE
|
||||
)
|
||||
ioctl(self.fd, I2C_SMBUS, msg)
|
||||
return msg.data.contents.byte
|
||||
|
||||
def write_byte(self, i2c_addr, value, force=None):
|
||||
"""
|
||||
Write a single byte to a device.
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param value: value to write
|
||||
:type value: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
"""
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_WRITE, command=value, size=I2C_SMBUS_BYTE
|
||||
)
|
||||
ioctl(self.fd, I2C_SMBUS, msg)
|
||||
|
||||
def read_byte_data(self, i2c_addr, register, force=None):
|
||||
"""
|
||||
Read a single byte from a designated register.
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Register to read
|
||||
:type register: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:return: Read byte value
|
||||
:rtype: int
|
||||
"""
|
||||
val_t = -1
|
||||
returnmsg=""
|
||||
try:
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BYTE_DATA
|
||||
)
|
||||
val_t = ioctl(self.fd, I2C_SMBUS, msg)
|
||||
except Exception as e:
|
||||
self.close()
|
||||
returnmsg = str(e)
|
||||
if val_t < 0:
|
||||
return False, returnmsg
|
||||
else:
|
||||
return True, msg.data.contents.byte
|
||||
|
||||
def write_byte_data(self, i2c_addr, register, value, force=None):
|
||||
"""
|
||||
Write a byte to a given register.
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Register to write to
|
||||
:type register: int
|
||||
:param value: Byte value to transmit
|
||||
:type value: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:rtype: None
|
||||
"""
|
||||
val_t = -1
|
||||
returnmsg = ""
|
||||
try:
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BYTE_DATA
|
||||
)
|
||||
msg.data.contents.byte = value
|
||||
val_t = ioctl(self.fd, I2C_SMBUS, msg)
|
||||
except Exception as e:
|
||||
returnmsg = str(e)
|
||||
self.close()
|
||||
if val_t < 0:
|
||||
return False, returnmsg or ""
|
||||
else:
|
||||
return True, ""
|
||||
|
||||
def write_byte_data_pec(self, i2c_addr, register, value, force=None):
|
||||
"""
|
||||
Write a byte to a given register.
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Register to write to
|
||||
:type register: int
|
||||
:param value: Byte value to transmit
|
||||
:type value: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:rtype: None
|
||||
"""
|
||||
val_t = -1
|
||||
returnmsg = ""
|
||||
try:
|
||||
val_t = ioctl(self.fd, I2C_PEC, 1)
|
||||
if val_t < 0:
|
||||
raise Exception("set pec mod error")
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BYTE_DATA
|
||||
)
|
||||
msg.data.contents.byte = value
|
||||
val_t = ioctl(self.fd, I2C_SMBUS, msg)
|
||||
except Exception as e:
|
||||
returnmsg = str(e)
|
||||
self.close()
|
||||
if val_t < 0:
|
||||
return False, returnmsg or ""
|
||||
else:
|
||||
return True, ""
|
||||
|
||||
def read_word_data(self, i2c_addr, register, force=None):
|
||||
"""
|
||||
Read a single word (2 bytes) from a given register.
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Register to read
|
||||
:type register: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:return: 2-byte word
|
||||
:rtype: int
|
||||
"""
|
||||
val_t = -1
|
||||
returnmsg = ""
|
||||
try:
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_WORD_DATA
|
||||
)
|
||||
val_t = ioctl(self.fd, I2C_SMBUS, msg)
|
||||
except Exception as e:
|
||||
returnmsg = str(e)
|
||||
self.close()
|
||||
if val_t < 0:
|
||||
return False, returnmsg or ""
|
||||
else:
|
||||
return True, msg.data.contents.word
|
||||
|
||||
def write_word_data_pec(self, i2c_addr, register, value, force=None):
|
||||
"""
|
||||
Write a byte to a given register.
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Register to write to
|
||||
:type register: int
|
||||
:param value: Word value to transmit
|
||||
:type value: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:rtype: None
|
||||
"""
|
||||
val_t = -1
|
||||
returnmsg = ""
|
||||
try:
|
||||
val_t = ioctl(self.fd, I2C_PEC, 1)
|
||||
if val_t < 0:
|
||||
raise Exception("set pec mod error")
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_WORD_DATA
|
||||
)
|
||||
msg.data.contents.word = value
|
||||
val_t = ioctl(self.fd, I2C_SMBUS, msg)
|
||||
except Exception as e:
|
||||
returnmsg = str(e)
|
||||
self.close()
|
||||
if val_t < 0:
|
||||
return False, returnmsg or ""
|
||||
else:
|
||||
return True, ""
|
||||
|
||||
def write_word_data(self, i2c_addr, register, value, force=None):
|
||||
"""
|
||||
Write a byte to a given register.
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Register to write to
|
||||
:type register: int
|
||||
:param value: Word value to transmit
|
||||
:type value: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:rtype: None
|
||||
"""
|
||||
val_t = -1
|
||||
returnmsg = ""
|
||||
try:
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_WORD_DATA
|
||||
)
|
||||
msg.data.contents.word = value
|
||||
val_t = ioctl(self.fd, I2C_SMBUS, msg)
|
||||
except Exception as e:
|
||||
returnmsg = str(e)
|
||||
self.close()
|
||||
if val_t < 0:
|
||||
return False, returnmsg or ""
|
||||
else:
|
||||
return True, ""
|
||||
|
||||
def process_call(self, i2c_addr, register, value, force=None):
|
||||
"""
|
||||
Executes a SMBus Process Call, sending a 16-bit value and receiving a 16-bit response
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Register to read/write to
|
||||
:type register: int
|
||||
:param value: Word value to transmit
|
||||
:type value: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:rtype: int
|
||||
"""
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_PROC_CALL
|
||||
)
|
||||
msg.data.contents.word = value
|
||||
ioctl(self.fd, I2C_SMBUS, msg)
|
||||
return msg.data.contents.word
|
||||
|
||||
def read_block_data(self, i2c_addr, register, force=None):
|
||||
"""
|
||||
Read a block of up to 32-bytes from a given register.
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Start register
|
||||
:type register: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:return: List of bytes
|
||||
:rtype: list
|
||||
"""
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BLOCK_DATA
|
||||
)
|
||||
ioctl(self.fd, I2C_SMBUS, msg)
|
||||
length = msg.data.contents.block[0]
|
||||
return msg.data.contents.block[1:length + 1]
|
||||
|
||||
def write_block_data(self, i2c_addr, register, data, force=None):
|
||||
"""
|
||||
Write a block of byte data to a given register.
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Start register
|
||||
:type register: int
|
||||
:param data: List of bytes
|
||||
:type data: list
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:rtype: None
|
||||
"""
|
||||
length = len(data)
|
||||
if length > I2C_SMBUS_BLOCK_MAX:
|
||||
raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX)
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_DATA
|
||||
)
|
||||
msg.data.contents.block[0] = length
|
||||
msg.data.contents.block[1:length + 1] = data
|
||||
ioctl(self.fd, I2C_SMBUS, msg)
|
||||
|
||||
def block_process_call(self, i2c_addr, register, data, force=None):
|
||||
"""
|
||||
Executes a SMBus Block Process Call, sending a variable-size data
|
||||
block and receiving another variable-size response
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Register to read/write to
|
||||
:type register: int
|
||||
:param data: List of bytes
|
||||
:type data: list
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:return: List of bytes
|
||||
:rtype: list
|
||||
"""
|
||||
length = len(data)
|
||||
if length > I2C_SMBUS_BLOCK_MAX:
|
||||
raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX)
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_PROC_CALL
|
||||
)
|
||||
msg.data.contents.block[0] = length
|
||||
msg.data.contents.block[1:length + 1] = data
|
||||
ioctl(self.fd, I2C_SMBUS, msg)
|
||||
length = msg.data.contents.block[0]
|
||||
return msg.data.contents.block[1:length + 1]
|
||||
|
||||
def read_i2c_block_data(self, i2c_addr, register, length, force=None):
|
||||
"""
|
||||
Read a block of byte data from a given register.
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Start register
|
||||
:type register: int
|
||||
:param length: Desired block length
|
||||
:type length: int
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:return: List of bytes
|
||||
:rtype: list
|
||||
"""
|
||||
if length > I2C_SMBUS_BLOCK_MAX:
|
||||
raise ValueError("Desired block length over %d bytes" % I2C_SMBUS_BLOCK_MAX)
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA
|
||||
)
|
||||
msg.data.contents.byte = length
|
||||
ioctl(self.fd, I2C_SMBUS, msg)
|
||||
return msg.data.contents.block[1:length + 1]
|
||||
|
||||
def write_i2c_block_data(self, i2c_addr, register, data, force=None):
|
||||
"""
|
||||
Write a block of byte data to a given register.
|
||||
|
||||
:param i2c_addr: i2c address
|
||||
:type i2c_addr: int
|
||||
:param register: Start register
|
||||
:type register: int
|
||||
:param data: List of bytes
|
||||
:type data: list
|
||||
:param force:
|
||||
:type force: Boolean
|
||||
:rtype: None
|
||||
"""
|
||||
length = len(data)
|
||||
if length > I2C_SMBUS_BLOCK_MAX:
|
||||
raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX)
|
||||
self._set_address(i2c_addr, force=force)
|
||||
msg = i2c_smbus_ioctl_data.create(
|
||||
read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA
|
||||
)
|
||||
msg.data.contents.block[0] = length
|
||||
msg.data.contents.block[1:length + 1] = data
|
||||
ioctl(self.fd, I2C_SMBUS, msg)
|
||||
|
||||
def i2c_rdwr(self, *i2c_msgs):
|
||||
"""
|
||||
Combine a series of i2c read and write operations in a single
|
||||
transaction (with repeated start bits but no stop bits in between).
|
||||
|
||||
This method takes i2c_msg instances as input, which must be created
|
||||
first with :py:meth:`i2c_msg.read` or :py:meth:`i2c_msg.write`.
|
||||
|
||||
:param i2c_msgs: One or more i2c_msg class instances.
|
||||
:type i2c_msgs: i2c_msg
|
||||
:rtype: None
|
||||
"""
|
||||
ioctl_data = i2c_rdwr_ioctl_data.create(*i2c_msgs)
|
||||
ioctl(self.fd, I2C_RDWR, ioctl_data)
|
||||
|
||||
|
||||
class SMBusWrapper:
|
||||
"""
|
||||
Wrapper class around the SMBus.
|
||||
Deprecated as of version 0.3.0. Please replace with :py:class:`SMBus`.
|
||||
|
||||
Enables the user to wrap access to the :py:class:`SMBus` class in a
|
||||
"with" statement. If auto_cleanup is True (default), the
|
||||
:py:class:`SMBus` handle will be automatically closed
|
||||
upon exit of the ``with`` block.
|
||||
"""
|
||||
def __init__(self, bus_number=0, auto_cleanup=True, force=False):
|
||||
"""
|
||||
:param auto_cleanup: Close bus when leaving scope.
|
||||
:type auto_cleanup: Boolean
|
||||
:param force: Force using the slave address even when driver is already using it.
|
||||
:type force: Boolean
|
||||
"""
|
||||
self.bus_number = bus_number
|
||||
self.auto_cleanup = auto_cleanup
|
||||
self.force = force
|
||||
|
||||
def __enter__(self):
|
||||
self.bus = SMBus(bus=self.bus_number, force=self.force)
|
||||
return self.bus
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
if self.auto_cleanup:
|
||||
self.bus.close()
|
@ -1,32 +0,0 @@
|
||||
PWD = $(shell pwd)
|
||||
EXTRA_CFLAGS:= -I$(M)/include
|
||||
EXTRA_CFLAGS+= -Wall
|
||||
KVERSION ?= $(shell uname -r)
|
||||
KERNEL_SRC ?= /lib/modules/$(KVERSION)
|
||||
|
||||
module_out_put_dir := $(PWD)/build
|
||||
export module_out_put_dir
|
||||
|
||||
ragile_common-objs := ragile_common_module.o dfd_tlveeprom.o
|
||||
obj-m += ragile_platform.o
|
||||
obj-m += i2c-mux-pca9641.o
|
||||
obj-m += i2c-mux-pca954x.o
|
||||
obj-m += ragile_common.o
|
||||
obj-m += rtcpcf85063.o
|
||||
#obj-m += tpm_tis_core.o
|
||||
#obj-m += rg_spi_gpio.o
|
||||
#obj-m += spi-gpio.o
|
||||
#obj-m += tpm_tis_spi.o
|
||||
obj-m += optoe.o
|
||||
obj-m += rg_at24.o
|
||||
|
||||
all :
|
||||
$(MAKE) -C $(KERNEL_SRC)/build M=$(PWD) modules
|
||||
@if [ ! -d $(module_out_put_dir) ]; then mkdir -p $(module_out_put_dir) ;fi
|
||||
cp -p $(PWD)/*.ko $(module_out_put_dir)
|
||||
|
||||
clean :
|
||||
rm -rf $(module_out_put_dir)
|
||||
rm -f ${PWD}/*.o ${PWD}/*.ko ${PWD}/*.mod.c ${PWD}/.*.cmd ${PWD}/.*.o.d
|
||||
rm -f ${PWD}/Module.markers ${PWD}/Module.symvers ${PWD}/modules.order
|
||||
rm -rf ${PWD}/.tmp_versions
|
@ -1,521 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2014 FreeIPMI Core Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/*****************************************************************************\
|
||||
* Copyright (C) 2007-2014 Lawrence Livermore National Security, LLC.
|
||||
* Copyright (C) 2007 The Regents of the University of California.
|
||||
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
||||
* Written by Albert Chu <chu11@llnl.gov>
|
||||
* UCRL-CODE-232183
|
||||
*
|
||||
* This file is part of Ipmi-fru, a tool used for retrieving
|
||||
* motherboard field replaceable unit (FRU) information. For details,
|
||||
* see http://www.llnl.gov/linux/.
|
||||
*
|
||||
* Ipmi-fru is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* Ipmi-fru is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with Ipmi-fru. If not, see <http://www.gnu.org/licenses/>.
|
||||
\*****************************************************************************/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include "ragile.h"
|
||||
#include "dfd_tlveeprom.h"
|
||||
|
||||
/* using in is_valid_tlvinfo_header */
|
||||
static u_int32_t eeprom_size;
|
||||
|
||||
/*
|
||||
* List of TLV codes and names.
|
||||
*/
|
||||
static const struct tlv_code_desc tlv_code_list[] = {
|
||||
{ TLV_CODE_PRODUCT_NAME , "Product Name"},
|
||||
{ TLV_CODE_PART_NUMBER , "Part Number"},
|
||||
{ TLV_CODE_SERIAL_NUMBER , "Serial Number"},
|
||||
{ TLV_CODE_MAC_BASE , "Base MAC Address"},
|
||||
{ TLV_CODE_MANUF_DATE , "Manufacture Date"},
|
||||
{ TLV_CODE_DEVICE_VERSION , "Device Version"},
|
||||
{ TLV_CODE_LABEL_REVISION , "Label Revision"},
|
||||
{ TLV_CODE_PLATFORM_NAME , "Platform Name"},
|
||||
{ TLV_CODE_ONIE_VERSION , "ONIE Version"},
|
||||
{ TLV_CODE_MAC_SIZE , "MAC Addresses"},
|
||||
{ TLV_CODE_MANUF_NAME , "Manufacturer"},
|
||||
{ TLV_CODE_MANUF_COUNTRY , "Country Code"},
|
||||
{ TLV_CODE_VENDOR_NAME , "Vendor Name"},
|
||||
{ TLV_CODE_DIAG_VERSION , "Diag Version"},
|
||||
{ TLV_CODE_SERVICE_TAG , "Service Tag"},
|
||||
{ TLV_CODE_VENDOR_EXT , "Vendor Extension"},
|
||||
{ TLV_CODE_CRC_32 , "CRC-32"},
|
||||
};
|
||||
|
||||
#if 0
|
||||
#define OPENBMC_VPD_KEY_INVAIL_VAL 0
|
||||
|
||||
static const tlv_code_map_t tlv_code_map[] = {
|
||||
{ TLV_CODE_PRODUCT_NAME , OPENBMC_VPD_KEY_PRODUCT_NAME},
|
||||
{ TLV_CODE_PART_NUMBER , OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM},
|
||||
{ TLV_CODE_SERIAL_NUMBER , OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM},
|
||||
{ TLV_CODE_MAC_BASE , OPENBMC_VPD_KEY_INVAIL_VAL},
|
||||
{ TLV_CODE_MANUF_DATE , OPENBMC_VPD_KEY_BOARD_MFG_DATE},
|
||||
{ TLV_CODE_DEVICE_VERSION , OPENBMC_VPD_KEY_PRODUCT_VER},
|
||||
{ TLV_CODE_LABEL_REVISION , OPENBMC_VPD_KEY_PRODUCT_CUSTOM7},
|
||||
{ TLV_CODE_PLATFORM_NAME , OPENBMC_VPD_KEY_PRODUCT_CUSTOM1},
|
||||
{ TLV_CODE_ONIE_VERSION , OPENBMC_VPD_KEY_PRODUCT_CUSTOM2},
|
||||
{ TLV_CODE_MAC_SIZE , OPENBMC_VPD_KEY_INVAIL_VAL},
|
||||
{ TLV_CODE_MANUF_NAME , OPENBMC_VPD_KEY_PRODUCT_MFR},
|
||||
{ TLV_CODE_MANUF_COUNTRY , OPENBMC_VPD_KEY_PRODUCT_CUSTOM3},
|
||||
{ TLV_CODE_VENDOR_NAME , OPENBMC_VPD_KEY_PRODUCT_CUSTOM4},
|
||||
{ TLV_CODE_DIAG_VERSION , OPENBMC_VPD_KEY_PRODUCT_CUSTOM8},
|
||||
{ TLV_CODE_SERVICE_TAG , OPENBMC_VPD_KEY_PRODUCT_CUSTOM5},
|
||||
{ TLV_CODE_VENDOR_EXT , OPENBMC_VPD_KEY_PRODUCT_CUSTOM6},
|
||||
{ TLV_CODE_CRC_32 , OPENBMC_VPD_KEY_INVAIL_VAL},
|
||||
};
|
||||
#endif
|
||||
|
||||
#define TLV_CODE_NUM (sizeof(tlv_code_list) / sizeof(tlv_code_list[0]))
|
||||
|
||||
#if 0
|
||||
#define TLV_CODE_MAP_NUM (sizeof(tlv_code_map) / sizeof(tlv_code_map[0]))
|
||||
#endif
|
||||
|
||||
const unsigned long crc_table[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
};
|
||||
|
||||
static unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned len)
|
||||
{
|
||||
unsigned i;
|
||||
if (len < 1)
|
||||
return 0xffffffff;
|
||||
|
||||
for (i = 0; i != len; ++i)
|
||||
{
|
||||
crc = crc_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
crc = crc ^ 0xffffffff;
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/*
|
||||
* is_valid_tlv
|
||||
*
|
||||
* Perform basic sanity checks on a TLV field. The TLV is pointed to
|
||||
* by the parameter provided.
|
||||
* 1. The type code is not reserved (0x00 or 0xFF)
|
||||
*/
|
||||
static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv)
|
||||
{
|
||||
return ((tlv->type != 0x00) && (tlv->type != 0xFF));
|
||||
}
|
||||
|
||||
/*
|
||||
* is_valid_tlvinfo_header
|
||||
*
|
||||
* Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM
|
||||
* data pointed to by the parameter:
|
||||
* 1. First 8 bytes contain null-terminated ASCII string "TlvInfo"
|
||||
* 2. Version byte is 1
|
||||
* 3. Total length bytes contain value which is less than or equal
|
||||
* to the allowed maximum (2048-11)
|
||||
*
|
||||
*/
|
||||
static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr)
|
||||
{
|
||||
int max_size = eeprom_size;
|
||||
return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) &&
|
||||
(hdr->version == TLV_INFO_VERSION) &&
|
||||
(be16_to_cpu(hdr->totallen) <= max_size) );
|
||||
}
|
||||
|
||||
/*
|
||||
* decode_tlv_value
|
||||
*
|
||||
* Decode a single TLV value into a string.
|
||||
|
||||
* The validity of EEPROM contents and the TLV field have been verified
|
||||
* prior to calling this function.
|
||||
*/
|
||||
static void decode_tlv_value(tlvinfo_tlv_t *tlv, tlv_decode_value_t *decode_value)
|
||||
{
|
||||
int i;
|
||||
char *value;
|
||||
u_int32_t length;
|
||||
|
||||
value = (char *)decode_value->value;
|
||||
|
||||
switch (tlv->type) {
|
||||
case TLV_CODE_PRODUCT_NAME:
|
||||
case TLV_CODE_PART_NUMBER:
|
||||
case TLV_CODE_SERIAL_NUMBER:
|
||||
case TLV_CODE_MANUF_DATE:
|
||||
case TLV_CODE_LABEL_REVISION:
|
||||
case TLV_CODE_PLATFORM_NAME:
|
||||
case TLV_CODE_ONIE_VERSION:
|
||||
case TLV_CODE_MANUF_NAME:
|
||||
case TLV_CODE_MANUF_COUNTRY:
|
||||
case TLV_CODE_VENDOR_NAME:
|
||||
case TLV_CODE_DIAG_VERSION:
|
||||
case TLV_CODE_SERVICE_TAG:
|
||||
case TLV_CODE_VENDOR_EXT:
|
||||
memcpy(value, tlv->value, tlv->length);
|
||||
value[tlv->length] = 0;
|
||||
length = tlv->length;
|
||||
break;
|
||||
case TLV_CODE_MAC_BASE:
|
||||
length = sprintf(value, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
tlv->value[0], tlv->value[1], tlv->value[2],
|
||||
tlv->value[3], tlv->value[4], tlv->value[5]);
|
||||
break;
|
||||
case TLV_CODE_DEVICE_VERSION:
|
||||
length = sprintf(value, "%u", tlv->value[0]);
|
||||
break;
|
||||
case TLV_CODE_MAC_SIZE:
|
||||
length = sprintf(value, "%u", (tlv->value[0] << 8) | tlv->value[1]);
|
||||
break;
|
||||
#if 0
|
||||
case TLV_CODE_VENDOR_EXT:
|
||||
value[0] = 0;
|
||||
length = 0;
|
||||
for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); i++) {
|
||||
length += sprintf(value, "%s 0x%02X", value, tlv->value[i]);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case TLV_CODE_CRC_32:
|
||||
length = sprintf(value, "0x%02X%02X%02X%02X", tlv->value[0],
|
||||
tlv->value[1], tlv->value[2], tlv->value[3]);
|
||||
break;
|
||||
default:
|
||||
value[0] = 0;
|
||||
length = 0;
|
||||
for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); i++) {
|
||||
length += sprintf(value, "%s 0x%02X", value, tlv->value[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
decode_value->length = length;
|
||||
}
|
||||
|
||||
/*
|
||||
* is_checksum_valid
|
||||
*
|
||||
* Validate the checksum in the provided TlvInfo EEPROM data. First,
|
||||
* verify that the TlvInfo header is valid, then make sure the last
|
||||
* TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data
|
||||
* and compare it to the value stored in the EEPROM CRC-32 TLV.
|
||||
*/
|
||||
static bool is_checksum_valid(u_int8_t *eeprom)
|
||||
{
|
||||
tlvinfo_header_t *eeprom_hdr;
|
||||
tlvinfo_tlv_t *eeprom_crc;
|
||||
unsigned int calc_crc;
|
||||
unsigned int stored_crc;
|
||||
|
||||
eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
|
||||
/* Is the eeprom header valid? */
|
||||
if (!is_valid_tlvinfo_header(eeprom_hdr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Is the last TLV a CRC? */
|
||||
eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) +
|
||||
be16_to_cpu(eeprom_hdr->totallen) - (sizeof(tlvinfo_tlv_t) + 4)];
|
||||
if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Calculate the checksum */
|
||||
calc_crc = crc32(0xffffffffL, (const unsigned char *)eeprom, sizeof(tlvinfo_header_t) +
|
||||
be16_to_cpu(eeprom_hdr->totallen) - 4);
|
||||
stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) |
|
||||
(eeprom_crc->value[2] << 8) | eeprom_crc->value[3]);
|
||||
|
||||
return (calc_crc == stored_crc);
|
||||
}
|
||||
|
||||
/*
|
||||
* tlvinfo_find_tlv
|
||||
*
|
||||
* This function finds the TLV with the supplied code in the EERPOM.
|
||||
* An offset from the beginning of the EEPROM is returned in the
|
||||
* eeprom_index parameter if the TLV is found.
|
||||
*/
|
||||
static bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, int *eeprom_index)
|
||||
{
|
||||
tlvinfo_header_t *eeprom_hdr;
|
||||
tlvinfo_tlv_t *eeprom_tlv;
|
||||
int eeprom_end;
|
||||
|
||||
eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
|
||||
/* Search through the TLVs, looking for the first one which matches the
|
||||
supplied type code. */
|
||||
*eeprom_index = sizeof(tlvinfo_header_t);
|
||||
eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen);
|
||||
while (*eeprom_index < eeprom_end) {
|
||||
eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index];
|
||||
if (!is_valid_tlv(eeprom_tlv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (eeprom_tlv->type == tcode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
*eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* tlvinfo_decode_tlv
|
||||
*
|
||||
* This function finds the TLV with the supplied code in the EERPOM
|
||||
* and decodes the value into the buffer provided.
|
||||
*/
|
||||
static bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, tlv_decode_value_t *decode_value)
|
||||
{
|
||||
int eeprom_index;
|
||||
tlvinfo_tlv_t *eeprom_tlv;
|
||||
|
||||
/* Find the TLV and then decode it */
|
||||
if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) {
|
||||
eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index];
|
||||
decode_tlv_value(eeprom_tlv, decode_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_tlv_eeprom
|
||||
*
|
||||
* parse the EEPROM into memory, if it hasn't already been read.
|
||||
*/
|
||||
int parse_tlv_eeprom(u_int8_t *eeprom, u_int32_t size)
|
||||
{
|
||||
unsigned int i;
|
||||
bool ret;
|
||||
tlvinfo_header_t *eeprom_hdr;
|
||||
//tlv_info_vec_t tlv_info;
|
||||
tlv_decode_value_t decode_value;
|
||||
int j;
|
||||
|
||||
eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
eeprom_size = size; /* eeprom real size */
|
||||
|
||||
if (!is_valid_tlvinfo_header(eeprom_hdr)) {
|
||||
DBG_ERROR("Failed to check tlv header.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!is_checksum_valid(eeprom)) {
|
||||
DBG_ERROR("Failed to check tlv crc.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < TLV_CODE_NUM; i++) {
|
||||
mem_clear((void *)&decode_value, sizeof(tlv_decode_value_t));
|
||||
ret = tlvinfo_decode_tlv(eeprom, tlv_code_list[i].m_code, &decode_value);
|
||||
if (!ret) {
|
||||
DBG_ERROR("No found type: %s\n", tlv_code_list[i].m_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
DBG_DEBUG("i: %d,Found type: %s tlv[%d]:%s\n", i, tlv_code_list[i].m_name, tlv_code_list[i].m_code,
|
||||
decode_value.value);
|
||||
for (j = 0; j < decode_value.length; j++) {
|
||||
if ((j % 16) == 0) {
|
||||
DBG_DEBUG("\n");
|
||||
}
|
||||
DBG_DEBUG("%02x ", decode_value.value[j]);
|
||||
}
|
||||
DBG_DEBUG("\n\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int dfd_parse_tlv_eeprom(u_int8_t *eeprom, u_int32_t size, u_int8_t main_type, tlv_decode_value_t *decode_value)
|
||||
{
|
||||
bool ret;
|
||||
tlvinfo_header_t *eeprom_hdr;
|
||||
/* tlv_info_vec_t tlv_info; */
|
||||
int j;
|
||||
|
||||
eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
eeprom_size = size; /* eeprom real size */
|
||||
|
||||
if (!is_valid_tlvinfo_header(eeprom_hdr)) {
|
||||
DBG_ERROR("Failed to check tlv header.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!is_checksum_valid(eeprom)) {
|
||||
DBG_ERROR("Failed to check tlv crc.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = tlvinfo_decode_tlv(eeprom, main_type, decode_value);
|
||||
if (!ret) {
|
||||
DBG_ERROR("No found type: %d\n", main_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DBG_DEBUG("Found type: %d, value: %s\n", main_type,decode_value->value);
|
||||
for (j = 0; j < decode_value->length; j++) {
|
||||
if ((j % 16) == 0) {
|
||||
DBG_DEBUG("\n");
|
||||
}
|
||||
DBG_DEBUG("%02x ", decode_value->value[j]);
|
||||
}
|
||||
DBG_DEBUG("\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* analyze the extended custom TLV format */
|
||||
static int tlvinfo_find_rg_ext_tlv(tlv_decode_value_t *ext_tlv_value, u_int8_t ext_type,
|
||||
u_int8_t *buf, u_int8_t *buf_len)
|
||||
{
|
||||
tlvinfo_tlv_t *eeprom_tlv;
|
||||
int eeprom_end, eeprom_index;
|
||||
|
||||
/* Search through the TLVs, looking for the first one which matches the
|
||||
supplied type code. */
|
||||
DBG_DEBUG("ext_tlv_value->length: %d.\n", ext_tlv_value->length);
|
||||
for (eeprom_index = 0; eeprom_index < ext_tlv_value->length; eeprom_index++) {
|
||||
if ((eeprom_index % 16) == 0) {
|
||||
DBG_DEBUG("\n");
|
||||
}
|
||||
DBG_DEBUG("%02x ", ext_tlv_value->value[eeprom_index]);
|
||||
}
|
||||
|
||||
DBG_DEBUG("\n");
|
||||
|
||||
eeprom_index = 0;
|
||||
eeprom_end = ext_tlv_value->length;
|
||||
while (eeprom_index < eeprom_end) {
|
||||
eeprom_tlv = (tlvinfo_tlv_t *) &(ext_tlv_value->value[eeprom_index]);
|
||||
if (!is_valid_tlv(eeprom_tlv)) {
|
||||
DBG_ERROR("tlv is not valid, eeprom_tlv->type 0x%x.\n", eeprom_tlv->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DBG_DEBUG("eeprom_tlv->length %d.\n", eeprom_tlv->length);
|
||||
if (eeprom_tlv->type == ext_type) {
|
||||
if (*buf_len >= eeprom_tlv->length) {
|
||||
memcpy(buf, eeprom_tlv->value, eeprom_tlv->length);
|
||||
DBG_DEBUG("eeprom_tlv->length %d.\n", eeprom_tlv->length);
|
||||
*buf_len = eeprom_tlv->length;
|
||||
return 0;
|
||||
}
|
||||
DBG_ERROR("buf_len %d small than info_len %d.\n", *buf_len, eeprom_tlv->length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length;
|
||||
}
|
||||
|
||||
DBG_ERROR("ext_type %d: tlv is not found.\n", ext_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get EEPROM information */
|
||||
int dfd_tlvinfo_get_e2prom_info(u_int8_t *eeprom, u_int32_t size, dfd_tlv_type_t *tlv_type, u_int8_t* buf, u_int8_t *buf_len)
|
||||
{
|
||||
tlv_decode_value_t decode_value;
|
||||
int ret;
|
||||
|
||||
if (eeprom == NULL || tlv_type == NULL || buf == NULL) {
|
||||
DBG_ERROR("Input para invalid.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mem_clear((void *)&decode_value, sizeof(tlv_decode_value_t));
|
||||
ret = dfd_parse_tlv_eeprom(eeprom, size, tlv_type->main_type, &decode_value);
|
||||
if (ret) {
|
||||
DBG_ERROR("dfd_parse_tlv_eeprom failed ret %d.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* For non-extended types, return data directly */
|
||||
if (tlv_type->main_type != TLV_CODE_VENDOR_EXT) {
|
||||
if (*buf_len >= decode_value.length) {
|
||||
memcpy(buf, decode_value.value, decode_value.length);
|
||||
*buf_len = decode_value.length;
|
||||
return 0;
|
||||
}
|
||||
DBG_ERROR("buf_len %d small than info_len %d.\n", *buf_len, decode_value.length);
|
||||
return -1;
|
||||
}
|
||||
DBG_DEBUG("info_len %d.\n", decode_value.length);
|
||||
|
||||
/* For the extended type, continue with the secondary TLV analysis to obtain
|
||||
the data corresponding to the sub-TLV type */
|
||||
return tlvinfo_find_rg_ext_tlv(&decode_value, tlv_type->ext_type, buf, buf_len);
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
#ifndef DFD_OPENBMC_TLVEEPROM_H
|
||||
#define DFD_OPENBMC_TLVEEPROM_H
|
||||
|
||||
#ifndef u_int8_t
|
||||
#define u_int8_t unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef u_int16_t
|
||||
#define u_int16_t unsigned short
|
||||
#endif
|
||||
|
||||
#ifndef u_int32_t
|
||||
#define u_int32_t unsigned int
|
||||
#endif
|
||||
|
||||
#ifndef be16_to_cpu
|
||||
#define be16_to_cpu(x) ntohs(x)
|
||||
#endif
|
||||
|
||||
#ifndef cpu_to_be16
|
||||
#define cpu_to_be16(x) htons(x)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The TLV Types.
|
||||
*
|
||||
* Keep these in sync with tlv_code_list in cmd_sys_eeprom.c
|
||||
*/
|
||||
#define TLV_CODE_PRODUCT_NAME 0x21
|
||||
#define TLV_CODE_PART_NUMBER 0x22
|
||||
#define TLV_CODE_SERIAL_NUMBER 0x23
|
||||
#define TLV_CODE_MAC_BASE 0x24
|
||||
#define TLV_CODE_MANUF_DATE 0x25
|
||||
#define TLV_CODE_DEVICE_VERSION 0x26
|
||||
#define TLV_CODE_LABEL_REVISION 0x27
|
||||
#define TLV_CODE_PLATFORM_NAME 0x28
|
||||
#define TLV_CODE_ONIE_VERSION 0x29
|
||||
#define TLV_CODE_MAC_SIZE 0x2A
|
||||
#define TLV_CODE_MANUF_NAME 0x2B
|
||||
#define TLV_CODE_MANUF_COUNTRY 0x2C
|
||||
#define TLV_CODE_VENDOR_NAME 0x2D
|
||||
#define TLV_CODE_DIAG_VERSION 0x2E
|
||||
#define TLV_CODE_SERVICE_TAG 0x2F
|
||||
#define TLV_CODE_VENDOR_EXT 0xFD
|
||||
#define TLV_CODE_CRC_32 0xFE
|
||||
|
||||
#define TLV_CODE_NAME_LEN 64
|
||||
/*
|
||||
* Struct for displaying the TLV codes and names.
|
||||
*/
|
||||
struct tlv_code_desc {
|
||||
u_int8_t m_code;
|
||||
char m_name[TLV_CODE_NAME_LEN];
|
||||
};
|
||||
/* ONIE TLV Type and Extended TLV Type Definition */
|
||||
typedef struct dfd_tlv_type_s {
|
||||
u_int8_t main_type;/* ONIE standard TLV TYPE type */
|
||||
u_int8_t ext_type; /* Extended TLV TYPE type */
|
||||
} dfd_tlv_type_t;
|
||||
|
||||
/* Header Field Constants */
|
||||
#define TLV_INFO_ID_STRING "TlvInfo"
|
||||
#define TLV_INFO_VERSION 0x01
|
||||
/*#define TLV_TOTAL_LEN_MAX (XXXXXXXX - sizeof(tlvinfo_header_t))*/
|
||||
|
||||
struct __attribute__ ((__packed__)) tlvinfo_header_s {
|
||||
char signature[8]; /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */
|
||||
u_int8_t version; /* 0x08 Structure version */
|
||||
u_int16_t totallen; /* 0x09 - 0x0A Length of all data which follows */
|
||||
};
|
||||
typedef struct tlvinfo_header_s tlvinfo_header_t;
|
||||
|
||||
/*
|
||||
* TlvInfo TLV: Layout of a TLV field
|
||||
*/
|
||||
struct __attribute__ ((__packed__)) tlvinfo_tlv_s {
|
||||
u_int8_t type;
|
||||
u_int8_t length;
|
||||
u_int8_t value[0];
|
||||
};
|
||||
typedef struct tlvinfo_tlv_s tlvinfo_tlv_t;
|
||||
|
||||
#define TLV_VALUE_MAX_LEN 255
|
||||
/*
|
||||
* The max decode value is currently for the 'raw' type or the 'vendor
|
||||
* extension' type, both of which have the same decode format. The
|
||||
* max decode string size is computed as follows:
|
||||
*
|
||||
* strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1
|
||||
*
|
||||
*/
|
||||
#define TLV_DECODE_VALUE_MAX_LEN ((5 * TLV_VALUE_MAX_LEN) + 1)
|
||||
|
||||
typedef struct tlv_decode_value_s {
|
||||
u_int8_t value[TLV_DECODE_VALUE_MAX_LEN];
|
||||
u_int32_t length;
|
||||
} tlv_decode_value_t;
|
||||
|
||||
typedef enum dfd_tlvinfo_ext_tlv_type_e {
|
||||
DFD_TLVINFO_EXT_TLV_TYPE_DEV_TYPE = 1,
|
||||
} dfd_tlvinfo_ext_tlv_type_t;
|
||||
|
||||
#if 0
|
||||
#define TLV_TIME_LEN 64
|
||||
|
||||
int ipmi_tlv_validate_fru_area(const uint8_t fruid, const char *fru_file_name,
|
||||
sd_bus *bus_type, const bool bmc_fru);
|
||||
|
||||
extern const char *get_vpd_key_names(int key_id);
|
||||
extern std::string getService(sdbusplus::bus::bus& bus,
|
||||
const std::string& intf,
|
||||
const std::string& path);
|
||||
extern std::string getFRUValue(const std::string& section,
|
||||
const std::string& key,
|
||||
const std::string& delimiter,
|
||||
IPMIFruInfo& fruData);
|
||||
#endif
|
||||
|
||||
int dfd_tlvinfo_get_e2prom_info(u_int8_t *eeprom, u_int32_t size, dfd_tlv_type_t *tlv_type, u_int8_t* buf, u_int8_t *buf_len);
|
||||
|
||||
#endif /* endif DFD_OPENBMC_TLVEEPROM_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,643 +0,0 @@
|
||||
/*
|
||||
* I2C multiplexer driver for PCA9541 bus master selector
|
||||
*
|
||||
* Copyright (c) 2010 Ericsson AB.
|
||||
*
|
||||
* Author: Guenter Roeck <linux@roeck-us.net>
|
||||
*
|
||||
* Derived from:
|
||||
* pca954x.c
|
||||
*
|
||||
* Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it>
|
||||
* Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
/*
|
||||
* The PCA9541 is a bus master selector. It supports two I2C masters connected
|
||||
* to a single slave bus.
|
||||
*
|
||||
* Before each bus transaction, a master has to acquire bus ownership. After the
|
||||
* transaction is complete, bus ownership has to be released. This fits well
|
||||
* into the I2C multiplexer framework, which provides select and release
|
||||
* functions for this purpose. For this reason, this driver is modeled as
|
||||
* single-channel I2C bus multiplexer.
|
||||
*
|
||||
* This driver assumes that the two bus masters are controlled by two different
|
||||
* hosts. If a single host controls both masters, platform code has to ensure
|
||||
* that only one of the masters is instantiated at any given time.
|
||||
*/
|
||||
|
||||
#define PCA9541_CONTROL 0x01
|
||||
#define PCA9541_ISTAT 0x02
|
||||
|
||||
#define PCA9541_CTL_MYBUS (1 << 0)
|
||||
#define PCA9541_CTL_NMYBUS (1 << 1)
|
||||
#define PCA9541_CTL_BUSON (1 << 2)
|
||||
#define PCA9541_CTL_NBUSON (1 << 3)
|
||||
#define PCA9541_CTL_BUSINIT (1 << 4)
|
||||
#define PCA9541_CTL_TESTON (1 << 6)
|
||||
#define PCA9541_CTL_NTESTON (1 << 7)
|
||||
#define PCA9541_ISTAT_INTIN (1 << 0)
|
||||
#define PCA9541_ISTAT_BUSINIT (1 << 1)
|
||||
#define PCA9541_ISTAT_BUSOK (1 << 2)
|
||||
#define PCA9541_ISTAT_BUSLOST (1 << 3)
|
||||
#define PCA9541_ISTAT_MYTEST (1 << 6)
|
||||
#define PCA9541_ISTAT_NMYTEST (1 << 7)
|
||||
#define PCA9641_ID 0x00
|
||||
#define PCA9641_ID_MAGIC 0x38
|
||||
#define PCA9641_CONTROL 0x01
|
||||
#define PCA9641_STATUS 0x02
|
||||
#define PCA9641_TIME 0x03
|
||||
#define PCA9641_CTL_LOCK_REQ BIT(0)
|
||||
#define PCA9641_CTL_LOCK_GRANT BIT(1)
|
||||
#define PCA9641_CTL_BUS_CONNECT BIT(2)
|
||||
#define PCA9641_CTL_BUS_INIT BIT(3)
|
||||
#define PCA9641_CTL_SMBUS_SWRST BIT(4)
|
||||
#define PCA9641_CTL_IDLE_TIMER_DIS BIT(5)
|
||||
#define PCA9641_CTL_SMBUS_DIS BIT(6)
|
||||
#define PCA9641_CTL_PRIORITY BIT(7)
|
||||
#define PCA9641_STS_OTHER_LOCK BIT(0)
|
||||
#define PCA9641_STS_BUS_INIT_FAIL BIT(1)
|
||||
#define PCA9641_STS_BUS_HUNG BIT(2)
|
||||
#define PCA9641_STS_MBOX_EMPTY BIT(3)
|
||||
#define PCA9641_STS_MBOX_FULL BIT(4)
|
||||
#define PCA9641_STS_TEST_INT BIT(5)
|
||||
#define PCA9641_STS_SCL_IO BIT(6)
|
||||
#define PCA9641_STS_SDA_IO BIT(7)
|
||||
#define PCA9641_RES_TIME 0x03
|
||||
#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON)
|
||||
#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS)
|
||||
#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS)
|
||||
#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON)
|
||||
#define BUSOFF(x, y) (!((x) & PCA9641_CTL_LOCK_GRANT) && \
|
||||
!((y) & PCA9641_STS_OTHER_LOCK))
|
||||
#define other_lock(x) ((x) & PCA9641_STS_OTHER_LOCK)
|
||||
#define lock_grant(x) ((x) & PCA9641_CTL_LOCK_GRANT)
|
||||
|
||||
#define PCA9641_RETRY_TIME 8
|
||||
|
||||
typedef struct i2c_muxs_struct_flag
|
||||
{
|
||||
int nr;
|
||||
char name[48];
|
||||
struct mutex update_lock;
|
||||
int flag;
|
||||
}i2c_mux_flag;
|
||||
|
||||
i2c_mux_flag pca_flag = {
|
||||
.flag = -1,
|
||||
};
|
||||
|
||||
int pca9641_setmuxflag(int nr, int flag)
|
||||
{
|
||||
if (pca_flag.nr == nr) {
|
||||
pca_flag.flag = flag;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pca9641_setmuxflag);
|
||||
|
||||
int g_debug = 0;
|
||||
module_param(g_debug, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
#define PCA_DEBUG(fmt, args...) do { \
|
||||
if (g_debug) { \
|
||||
printk(KERN_ERR "[pca9641][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* arbitration timeouts, in jiffies */
|
||||
#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */
|
||||
#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */
|
||||
|
||||
/* arbitration retry delays, in us */
|
||||
#define SELECT_DELAY_SHORT 50
|
||||
#define SELECT_DELAY_LONG 1000
|
||||
|
||||
struct pca9541 {
|
||||
struct i2c_client *client;
|
||||
unsigned long select_timeout;
|
||||
unsigned long arb_timeout;
|
||||
};
|
||||
|
||||
static const struct i2c_device_id pca9541_id[] = {
|
||||
{"pca9541", 0},
|
||||
{"pca9641", 1},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, pca9541_id);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id pca9541_of_match[] = {
|
||||
{ .compatible = "nxp,pca9541" },
|
||||
{ .compatible = "nxp,pca9641" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pca9541_of_match);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
|
||||
* as they will try to lock the adapter a second time.
|
||||
*/
|
||||
static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val)
|
||||
{
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
int ret;
|
||||
|
||||
if (adap->algo->master_xfer) {
|
||||
struct i2c_msg msg;
|
||||
char buf[2];
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.flags = 0;
|
||||
msg.len = 2;
|
||||
buf[0] = command;
|
||||
buf[1] = val;
|
||||
msg.buf = buf;
|
||||
ret = __i2c_transfer(adap, &msg, 1);
|
||||
} else {
|
||||
union i2c_smbus_data data;
|
||||
|
||||
data.byte = val;
|
||||
ret = adap->algo->smbus_xfer(adap, client->addr,
|
||||
client->flags,
|
||||
I2C_SMBUS_WRITE,
|
||||
command,
|
||||
I2C_SMBUS_BYTE_DATA, &data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
|
||||
* as they will try to lock adapter a second time.
|
||||
*/
|
||||
static int pca9541_reg_read(struct i2c_client *client, u8 command)
|
||||
{
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
if (adap->algo->master_xfer) {
|
||||
struct i2c_msg msg[2] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = &command
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = &val
|
||||
}
|
||||
};
|
||||
ret = __i2c_transfer(adap, msg, 2);
|
||||
if (ret == 2)
|
||||
ret = val;
|
||||
else if (ret >= 0)
|
||||
ret = -EIO;
|
||||
} else {
|
||||
union i2c_smbus_data data;
|
||||
|
||||
ret = adap->algo->smbus_xfer(adap, client->addr,
|
||||
client->flags,
|
||||
I2C_SMBUS_READ,
|
||||
command,
|
||||
I2C_SMBUS_BYTE_DATA, &data);
|
||||
if (!ret)
|
||||
ret = data.byte;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Arbitration management functions
|
||||
*/
|
||||
|
||||
/* Release bus. Also reset NTESTON and BUSINIT if it was set. */
|
||||
static void pca9541_release_bus(struct i2c_client *client)
|
||||
{
|
||||
int reg;
|
||||
|
||||
reg = pca9541_reg_read(client, PCA9541_CONTROL);
|
||||
if (reg >= 0 && !busoff(reg) && mybus(reg))
|
||||
pca9541_reg_write(client, PCA9541_CONTROL,
|
||||
(reg & PCA9541_CTL_NBUSON) >> 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Arbitration is defined as a two-step process. A bus master can only activate
|
||||
* the slave bus if it owns it; otherwise it has to request ownership first.
|
||||
* This multi-step process ensures that access contention is resolved
|
||||
* gracefully.
|
||||
*
|
||||
* Bus Ownership Other master Action
|
||||
* state requested access
|
||||
* ----------------------------------------------------
|
||||
* off - yes wait for arbitration timeout or
|
||||
* for other master to drop request
|
||||
* off no no take ownership
|
||||
* off yes no turn on bus
|
||||
* on yes - done
|
||||
* on no - wait for arbitration timeout or
|
||||
* for other master to release bus
|
||||
*
|
||||
* The main contention point occurs if the slave bus is off and both masters
|
||||
* request ownership at the same time. In this case, one master will turn on
|
||||
* the slave bus, believing that it owns it. The other master will request
|
||||
* bus ownership. Result is that the bus is turned on, and master which did
|
||||
* _not_ own the slave bus before ends up owning it.
|
||||
*/
|
||||
|
||||
/* Control commands per PCA9541 datasheet */
|
||||
static const u8 pca9541_control[16] = {
|
||||
4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1
|
||||
};
|
||||
|
||||
/*
|
||||
* Channel arbitration
|
||||
*
|
||||
* Return values:
|
||||
* <0: error
|
||||
* 0 : bus not acquired
|
||||
* 1 : bus acquired
|
||||
*/
|
||||
static int pca9541_arbitrate(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
|
||||
struct pca9541 *data = i2c_mux_priv(muxc);
|
||||
int reg;
|
||||
|
||||
reg = pca9541_reg_read(client, PCA9541_CONTROL);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
if (busoff(reg)) {
|
||||
int istat;
|
||||
/*
|
||||
* Bus is off. Request ownership or turn it on unless
|
||||
* other master requested ownership.
|
||||
*/
|
||||
istat = pca9541_reg_read(client, PCA9541_ISTAT);
|
||||
if (!(istat & PCA9541_ISTAT_NMYTEST)
|
||||
|| time_is_before_eq_jiffies(data->arb_timeout)) {
|
||||
/*
|
||||
* Other master did not request ownership,
|
||||
* or arbitration timeout expired. Take the bus.
|
||||
*/
|
||||
pca9541_reg_write(client,
|
||||
PCA9541_CONTROL,
|
||||
pca9541_control[reg & 0x0f]
|
||||
| PCA9541_CTL_NTESTON);
|
||||
data->select_timeout = SELECT_DELAY_SHORT;
|
||||
} else {
|
||||
/*
|
||||
* Other master requested ownership.
|
||||
* Set extra long timeout to give it time to acquire it.
|
||||
*/
|
||||
data->select_timeout = SELECT_DELAY_LONG * 2;
|
||||
}
|
||||
} else if (mybus(reg)) {
|
||||
/*
|
||||
* Bus is on, and we own it. We are done with acquisition.
|
||||
* Reset NTESTON and BUSINIT, then return success.
|
||||
*/
|
||||
if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT))
|
||||
pca9541_reg_write(client,
|
||||
PCA9541_CONTROL,
|
||||
reg & ~(PCA9541_CTL_NTESTON
|
||||
| PCA9541_CTL_BUSINIT));
|
||||
return 1;
|
||||
} else {
|
||||
/*
|
||||
* Other master owns the bus.
|
||||
* If arbitration timeout has expired, force ownership.
|
||||
* Otherwise request it.
|
||||
*/
|
||||
data->select_timeout = SELECT_DELAY_LONG;
|
||||
if (time_is_before_eq_jiffies(data->arb_timeout)) {
|
||||
/* Time is up, take the bus and reset it. */
|
||||
pca9541_reg_write(client,
|
||||
PCA9541_CONTROL,
|
||||
pca9541_control[reg & 0x0f]
|
||||
| PCA9541_CTL_BUSINIT
|
||||
| PCA9541_CTL_NTESTON);
|
||||
} else {
|
||||
/* Request bus ownership if needed */
|
||||
if (!(reg & PCA9541_CTL_NTESTON))
|
||||
pca9541_reg_write(client,
|
||||
PCA9541_CONTROL,
|
||||
reg | PCA9541_CTL_NTESTON);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
struct pca9541 *data = i2c_mux_priv(muxc);
|
||||
struct i2c_client *client = data->client;
|
||||
int ret;
|
||||
unsigned long timeout = jiffies + ARB2_TIMEOUT;
|
||||
/* give up after this time */
|
||||
|
||||
data->arb_timeout = jiffies + ARB_TIMEOUT;
|
||||
/* force bus ownership after this time */
|
||||
|
||||
do {
|
||||
ret = pca9541_arbitrate(client);
|
||||
if (ret)
|
||||
return ret < 0 ? ret : 0;
|
||||
|
||||
if (data->select_timeout == SELECT_DELAY_SHORT)
|
||||
udelay(data->select_timeout);
|
||||
else
|
||||
msleep(data->select_timeout / 1000);
|
||||
} while (time_is_after_eq_jiffies(timeout));
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
struct pca9541 *data = i2c_mux_priv(muxc);
|
||||
struct i2c_client *client = data->client;
|
||||
pca9541_release_bus(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Arbitration management functions
|
||||
*/
|
||||
static void pca9641_release_bus(struct i2c_client *client)
|
||||
{
|
||||
pca9541_reg_write(client, PCA9641_CONTROL, 0x80); /* master 0x80 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Channel arbitration
|
||||
*
|
||||
* Return values:
|
||||
* <0: error
|
||||
* 0 : bus not acquired
|
||||
* 1 : bus acquired
|
||||
*/
|
||||
static int pca9641_arbitrate(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
|
||||
struct pca9541 *data = i2c_mux_priv(muxc);
|
||||
int reg_ctl, reg_sts;
|
||||
|
||||
reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL);
|
||||
if (reg_ctl < 0)
|
||||
return reg_ctl;
|
||||
reg_sts = pca9541_reg_read(client, PCA9641_STATUS);
|
||||
|
||||
if (BUSOFF(reg_ctl, reg_sts)) {
|
||||
/*
|
||||
* Bus is off. Request ownership or turn it on unless
|
||||
* other master requested ownership.
|
||||
*/
|
||||
reg_ctl |= PCA9641_CTL_LOCK_REQ;
|
||||
pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl);
|
||||
reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL);
|
||||
|
||||
if (lock_grant(reg_ctl)) {
|
||||
/*
|
||||
* Other master did not request ownership,
|
||||
* or arbitration timeout expired. Take the bus.
|
||||
*/
|
||||
reg_ctl |= PCA9641_CTL_BUS_CONNECT
|
||||
| PCA9641_CTL_LOCK_REQ;
|
||||
pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl);
|
||||
data->select_timeout = SELECT_DELAY_SHORT;
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
/*
|
||||
* Other master requested ownership.
|
||||
* Set extra long timeout to give it time to acquire it.
|
||||
*/
|
||||
data->select_timeout = SELECT_DELAY_LONG * 2;
|
||||
}
|
||||
} else if (lock_grant(reg_ctl)) {
|
||||
/*
|
||||
* Bus is on, and we own it. We are done with acquisition.
|
||||
*/
|
||||
reg_ctl |= PCA9641_CTL_BUS_CONNECT | PCA9641_CTL_LOCK_REQ;
|
||||
pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl);
|
||||
|
||||
return 1;
|
||||
} else if (other_lock(reg_sts)) {
|
||||
/*
|
||||
* Other master owns the bus.
|
||||
* If arbitration timeout has expired, force ownership.
|
||||
* Otherwise request it.
|
||||
*/
|
||||
data->select_timeout = SELECT_DELAY_LONG;
|
||||
reg_ctl |= PCA9641_CTL_LOCK_REQ;
|
||||
pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pca9641_select_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
struct pca9541 *data = i2c_mux_priv(muxc);
|
||||
struct i2c_client *client = data->client;
|
||||
int ret;
|
||||
int result;
|
||||
unsigned long timeout = jiffies + ARB2_TIMEOUT;
|
||||
/* give up after this time */
|
||||
data->arb_timeout = jiffies + ARB_TIMEOUT;
|
||||
/* force bus ownership after this time */
|
||||
for (result = 0 ; result < PCA9641_RETRY_TIME ; result ++) {
|
||||
do {
|
||||
ret = pca9641_arbitrate(client);
|
||||
if (ret == 1) {
|
||||
return 0;
|
||||
}
|
||||
if (data->select_timeout == SELECT_DELAY_SHORT)
|
||||
udelay(data->select_timeout);
|
||||
else
|
||||
msleep(data->select_timeout / 1000);
|
||||
} while (time_is_after_eq_jiffies(timeout));
|
||||
timeout = jiffies + ARB2_TIMEOUT;
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
EXPORT_SYMBOL(pca9641_select_chan);
|
||||
|
||||
static int pca9641_release_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
struct pca9541 *data = i2c_mux_priv(muxc);
|
||||
struct i2c_client *client = data->client;
|
||||
if (pca_flag.flag) {
|
||||
pca9641_release_bus(client);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pca9641_detect_id(struct i2c_client *client)
|
||||
{
|
||||
int reg;
|
||||
|
||||
reg = pca9541_reg_read(client, PCA9641_ID);
|
||||
if (reg == PCA9641_ID_MAGIC)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Limited: 20180827 supports one PCA9641
|
||||
**/
|
||||
static int pca9641_recordflag(struct i2c_adapter *adap) {
|
||||
if (pca_flag.flag != -1) {
|
||||
pr_err(" %s %d has init already!!!", __func__, __LINE__);
|
||||
return -1 ;
|
||||
}
|
||||
pca_flag.nr = adap->nr;
|
||||
PCA_DEBUG(" adap->nr:%d\n", adap->nr);
|
||||
snprintf(pca_flag.name, sizeof(pca_flag.name),adap->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i2c_lock_adapter(struct i2c_adapter *adapter){
|
||||
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
|
||||
if (parent)
|
||||
i2c_lock_adapter(parent);
|
||||
else
|
||||
rt_mutex_lock(&adapter->bus_lock);
|
||||
}
|
||||
|
||||
void i2c_unlock_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
|
||||
|
||||
if (parent)
|
||||
i2c_unlock_adapter(parent);
|
||||
else
|
||||
rt_mutex_unlock(&adapter->bus_lock);
|
||||
}
|
||||
/*
|
||||
* I2C init/probing/exit functions
|
||||
*/
|
||||
static int pca9541_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct i2c_mux_core *muxc;
|
||||
struct pca9541 *data;
|
||||
int force;
|
||||
int ret = -ENODEV;
|
||||
int detect_id;
|
||||
|
||||
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
detect_id = pca9641_detect_id(client);
|
||||
|
||||
/*
|
||||
* I2C accesses are unprotected here.
|
||||
* We have to lock the adapter before releasing the bus.
|
||||
*/
|
||||
#if 0
|
||||
i2c_lock_adapter(adap);
|
||||
pca9541_release_bus(client);
|
||||
i2c_unlock_adapter(adap);
|
||||
#endif
|
||||
if (detect_id == 0) {
|
||||
i2c_lock_adapter(adap);
|
||||
pca9541_release_bus(client);
|
||||
i2c_unlock_adapter(adap);
|
||||
} else {
|
||||
i2c_lock_adapter(adap);
|
||||
pca9641_release_bus(client);
|
||||
i2c_unlock_adapter(adap);
|
||||
}
|
||||
|
||||
/* Create mux adapter */
|
||||
|
||||
if (detect_id == 0) {
|
||||
muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data),
|
||||
I2C_MUX_ARBITRATOR,
|
||||
pca9541_select_chan, pca9541_release_chan);
|
||||
if (!muxc)
|
||||
return -ENOMEM;
|
||||
|
||||
data = i2c_mux_priv(muxc);
|
||||
data->client = client;
|
||||
|
||||
i2c_set_clientdata(client, muxc);
|
||||
ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data),
|
||||
I2C_MUX_ARBITRATOR,
|
||||
pca9641_select_chan, pca9641_release_chan);
|
||||
if (!muxc)
|
||||
return -ENOMEM;
|
||||
|
||||
data = i2c_mux_priv(muxc);
|
||||
data->client = client;
|
||||
|
||||
i2c_set_clientdata(client, muxc);
|
||||
|
||||
ret = i2c_mux_add_adapter(muxc, force, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
pca9641_recordflag(muxc->adapter[0]);
|
||||
|
||||
dev_info(&client->dev, "registered master selector for I2C %s\n",
|
||||
client->name);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int pca9541_remove(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
|
||||
|
||||
i2c_mux_del_adapters(muxc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver pca9641_driver = {
|
||||
.driver = {
|
||||
.name = "pca9641",
|
||||
.of_match_table = of_match_ptr(pca9541_of_match),
|
||||
},
|
||||
.probe = pca9541_probe,
|
||||
.remove = pca9541_remove,
|
||||
.id_table = pca9541_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(pca9641_driver);
|
||||
|
||||
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
|
||||
MODULE_DESCRIPTION("PCA9541 I2C master selector driver");
|
||||
MODULE_LICENSE("GPL v2");
|
File diff suppressed because it is too large
Load Diff
@ -1,158 +0,0 @@
|
||||
#ifndef __RAGILE_H__
|
||||
#define __RAGILE_H__
|
||||
|
||||
#include<linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#define mem_clear(data, size) memset((data), 0, (size))
|
||||
|
||||
/* debug switch level */
|
||||
typedef enum {
|
||||
DBG_START,
|
||||
DBG_VERBOSE,
|
||||
DBG_KEY,
|
||||
DBG_WARN,
|
||||
DBG_ERROR,
|
||||
DBG_END,
|
||||
} dbg_level_t;
|
||||
|
||||
typedef enum dfd_cpld_id {
|
||||
BCM_CPLD0 = 0,
|
||||
BCM_CPLD1,
|
||||
CPLD0_MAC0,
|
||||
CPLD0_MAC1,
|
||||
CPLD1_MAC0,
|
||||
CPLD2_MAC1,
|
||||
} dfd_cpld_id_t;
|
||||
|
||||
typedef enum dfd_cpld_bus {
|
||||
SMBUS_BUS = 0 ,
|
||||
GPIO_BUS = 1,
|
||||
PCA9641_BUS = 2,
|
||||
} dfd_cpld_bus_t;
|
||||
|
||||
typedef struct dfd_i2c_dev_s {
|
||||
int bus; /* bus number */
|
||||
int addr; /* bus address */
|
||||
} dfd_i2c_dev_t;
|
||||
|
||||
typedef enum dfd_cpld_addr {
|
||||
CPLD_ADDR_MIN = 0x31,
|
||||
BCM_CPLD0_ADDR = 0x32, /* pca9641 up */
|
||||
CPLD0_MAC0_ADDR = 0x33, /* SMBUS down */
|
||||
CPLD0_MAC1_ADDR = 0x34,
|
||||
CPLD1_MAC0_ADDR = 0x35,
|
||||
CPLD2_MAC1_ADDR = 0x36,
|
||||
BCM_CPLD1_ADDR = 0x37,
|
||||
CPLD_ADDR_MAX,
|
||||
} dfd_cpld_addr_t;
|
||||
|
||||
typedef struct dfd_dev_head_info_s {
|
||||
uint8_t ver; /* The version number defined by the E2PROM file, the initial version is 0x01 */
|
||||
uint8_t flag; /* The new version of E2PROM is identified as 0x7E */
|
||||
uint8_t hw_ver; /* It consists of two parts: the main version number and the revised version */
|
||||
uint8_t type; /* Hardware type definition information */
|
||||
int16_t tlv_len; /* Effective data length (16 bits) */
|
||||
} dfd_dev_head_info_t;
|
||||
|
||||
typedef enum dfd_intf_e{
|
||||
DFD_INTF_GET_FAN_HW_VERSION,
|
||||
DFD_INTF_GET_FAN_STATUS,
|
||||
DFD_INTF_GET_FAN_SPEED_LEVEL,
|
||||
DFD_INTF_GET_FAN_SPEED,
|
||||
DFD_INTF_GET_FAN_ATTRIBUTE,
|
||||
DFD_INTF_GET_FAN_SN,
|
||||
DFD_INTF_GET_FAN_TYPE,
|
||||
DFD_INTF_SET_FAN_SPEED_LEVEL,
|
||||
DFD_INTF_GET_FAN_SUB_NUM,
|
||||
DFD_INTF_GET_FAN_FAIL_BITMAP,
|
||||
}dfd_intf_t;
|
||||
|
||||
typedef struct dfd_dev_tlv_info_s {
|
||||
uint8_t type; /* the type of data */
|
||||
uint8_t len; /* the length of data */
|
||||
uint8_t data[0]; /* data */
|
||||
} dfd_dev_tlv_info_t;
|
||||
|
||||
typedef enum dfd_dev_info_type_e {
|
||||
DFD_DEV_INFO_TYPE_MAC = 1,
|
||||
DFD_DEV_INFO_TYPE_NAME = 2,
|
||||
DFD_DEV_INFO_TYPE_SN = 3,
|
||||
DFD_DEV_INFO_TYPE_PWR_CONS = 4,
|
||||
DFD_DEV_INFO_TYPE_HW_INFO = 5,
|
||||
DFD_DEV_INFO_TYPE_DEV_TYPE = 6,
|
||||
} dfd_dev_tlv_type_t;
|
||||
|
||||
struct sfp_drivers_t{
|
||||
/* addr = sff present bitmap addr, index from 0 */
|
||||
void (*get_number) (unsigned int *number);
|
||||
int (*get_port_start) (void);
|
||||
int (*get_port_end) (void);
|
||||
bool (*is_qsfp_port) (const unsigned int port_num);
|
||||
bool (*get_present) (unsigned long *bitmap);
|
||||
bool (*read_sfp_eeprom) (const unsigned int port,
|
||||
const unsigned char addr,
|
||||
const unsigned char offset,
|
||||
const uint32_t count, char *buf);
|
||||
bool (*write_sfp_eeprom) (const unsigned int port,
|
||||
const unsigned char addr,
|
||||
const unsigned char offset,
|
||||
const unsigned char count,
|
||||
const char *buf);
|
||||
bool (*read_sysfs) (const unsigned int bus,
|
||||
const unsigned char addr,
|
||||
const unsigned char offset,
|
||||
const uint32_t count, char *buf);
|
||||
bool (*write_sysfs) (const unsigned int bus,
|
||||
const unsigned char addr,
|
||||
const unsigned char offset,
|
||||
const unsigned char count,
|
||||
const char *buf);
|
||||
bool (*read_block_sysfs) (const unsigned int bus,
|
||||
const unsigned char addr,
|
||||
const unsigned char offset,
|
||||
const uint32_t count, char *buf);
|
||||
};
|
||||
|
||||
extern int debuglevel;
|
||||
extern int dfd_cpld_read_chipid(int cpldid , uint32_t addr, int32_t size, unsigned char *buf);
|
||||
extern int dfd_cpld_read(int32_t addr, uint8_t *val);
|
||||
extern int dfd_cpld_write(int32_t addr, uint8_t val);
|
||||
extern int rg_i2c_read(uint32_t bus, uint32_t addr, uint32_t offset, uint32_t size, unsigned char *buf) ;
|
||||
extern int rg_i2c_write(uint32_t bus, uint32_t addr, uint32_t offset, uint8_t buf);
|
||||
extern int rg_i2c_read_block(uint32_t bus, uint32_t addr, uint32_t offset, uint32_t size, unsigned char *buf) ;
|
||||
extern int ragile_setdebug(int val);
|
||||
extern s32 platform_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command);
|
||||
extern s32 platform_i2c_smbus_read_i2c_block_data(const struct i2c_client *client,
|
||||
u8 command, u8 length, u8 *values);
|
||||
extern s32 platform_i2c_smbus_read_word_data(const struct i2c_client *client, u8 command);
|
||||
|
||||
extern int sfp_drivers_register(struct sfp_drivers_t *drv);
|
||||
extern int sfp_drivers_unregister(void);
|
||||
|
||||
extern int sysfs_drivers_register(struct sfp_drivers_t *drv);
|
||||
extern int sysfs_drivers_unregister(void);
|
||||
|
||||
#define DBG_DEBUG(fmt, arg...) do { \
|
||||
if ( debuglevel > DBG_START && debuglevel < DBG_ERROR) { \
|
||||
printk(KERN_INFO "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \
|
||||
} else if ( debuglevel >= DBG_ERROR ) { \
|
||||
printk(KERN_ERR "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \
|
||||
} else { } \
|
||||
} while (0)
|
||||
|
||||
#define DBG_INFO(fmt, arg...) do { \
|
||||
if ( debuglevel > DBG_KEY) { \
|
||||
printk(KERN_INFO "[INFO]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DBG_ERROR(fmt, arg...) do { \
|
||||
if ( debuglevel > DBG_START) { \
|
||||
printk(KERN_ERR "[ERROR]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
@ -1,210 +0,0 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/platform_data/i2c-mux-gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c-smbus.h>
|
||||
#include <linux/string.h>
|
||||
#include "ragile.h"
|
||||
#include "dfd_tlveeprom.h"
|
||||
|
||||
#define PLATFORM_I2C_RETRY_TIMES 3
|
||||
|
||||
#define DFD_TLVEEPROM_I2C_BUS (0)
|
||||
#define DFD_TLVEEPROM_I2C_ADDR (0x56)
|
||||
#define DFD_E2PROM_MAX_LEN (256)
|
||||
#define DFD_CARDTYPE_EXT_TLVLEN (4)
|
||||
|
||||
#define PLATFORM_CARDTYPE_RETRY_CNT (10)
|
||||
#define PLATFORM_CARDTYPE_RETRY_TIMES (1000)
|
||||
|
||||
int debuglevel = 0;
|
||||
module_param(debuglevel, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
static int dfd_my_type = 0;
|
||||
module_param(dfd_my_type, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
int g_common_debug_error = 0;
|
||||
module_param(g_common_debug_error, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
int g_common_debug_verbose = 0;
|
||||
module_param(g_common_debug_verbose, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
uint32_t dfd_my_type_i2c_bus = 0;
|
||||
module_param(dfd_my_type_i2c_bus, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
uint32_t dfd_my_type_i2c_addr = 0;
|
||||
module_param(dfd_my_type_i2c_addr, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
#define RAGILE_COMMON_DEBUG_VERBOSE(fmt, args...) do { \
|
||||
if (g_common_debug_verbose) { \
|
||||
printk(KERN_ERR "[RAGILE_COMMON][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RAGILE_COMMON_DEBUG_ERROR(fmt, args...) do { \
|
||||
if (g_common_debug_error) { \
|
||||
printk(KERN_ERR "[RAGILE_COMMON][ERROR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int32_t dfd_i2c_read(char *dev, uint32_t addr, uint32_t offset_addr, unsigned char *
|
||||
buf, int32_t size)
|
||||
{
|
||||
struct file *fp;
|
||||
mm_segment_t fs;
|
||||
struct i2c_client client;
|
||||
int i ,j ;
|
||||
int rv;
|
||||
s32 val_t;
|
||||
|
||||
val_t = -1;
|
||||
rv = 0;
|
||||
fp = filp_open(dev, O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (IS_ERR(fp)) {
|
||||
DBG_ERROR("i2c open fail.\n");
|
||||
RAGILE_COMMON_DEBUG_ERROR("i2c open fail.\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(&client, fp->private_data, sizeof(struct i2c_client));
|
||||
client.addr = addr;
|
||||
fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
for (j = 0 ;j < size ;j++){
|
||||
for (i = 0; i < PLATFORM_I2C_RETRY_TIMES; i++) {
|
||||
if ((val_t = i2c_smbus_read_byte_data(&client, (offset_addr + j))) < 0) {
|
||||
DBG_DEBUG("read try(%d)time offset_addr:%x \n", i, offset_addr);
|
||||
continue;
|
||||
} else {
|
||||
* (buf + j) = val_t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (val_t < 0) {
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
filp_close(fp, NULL);
|
||||
set_fs(fs);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int dfd_tlvinfo_get_cardtype(void)
|
||||
{
|
||||
char i2c_path[16] = {0};
|
||||
int ret;
|
||||
int cardtype;
|
||||
u_int8_t eeprom[DFD_E2PROM_MAX_LEN];
|
||||
dfd_i2c_dev_t i2c_dev;
|
||||
uint8_t buf[DFD_CARDTYPE_EXT_TLVLEN];
|
||||
uint8_t len;
|
||||
dfd_tlv_type_t tlv_type;
|
||||
|
||||
if (dfd_my_type_i2c_bus != 0) {
|
||||
i2c_dev.bus = dfd_my_type_i2c_bus;
|
||||
} else {
|
||||
i2c_dev.bus = DFD_TLVEEPROM_I2C_BUS;
|
||||
}
|
||||
|
||||
if (dfd_my_type_i2c_addr != 0) {
|
||||
i2c_dev.addr = dfd_my_type_i2c_addr;
|
||||
} else {
|
||||
i2c_dev.addr = DFD_TLVEEPROM_I2C_ADDR;
|
||||
}
|
||||
snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", i2c_dev.bus);
|
||||
RAGILE_COMMON_DEBUG_VERBOSE("Read device eeprom info:(dev:%s, addr:%02x).\n", i2c_path, i2c_dev.addr);
|
||||
|
||||
ret = dfd_i2c_read(i2c_path, i2c_dev.addr, 0, eeprom, DFD_E2PROM_MAX_LEN);
|
||||
if (ret != 0) {
|
||||
DBG_ERROR("Read eeprom info error(dev: %s, addr: %02x).\n", i2c_path, i2c_dev.addr);
|
||||
RAGILE_COMMON_DEBUG_ERROR("Read eeprom info error(dev: %s, addr: %02x).\n", i2c_path, i2c_dev.addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tlv_type.main_type = TLV_CODE_VENDOR_EXT;
|
||||
tlv_type.ext_type = DFD_TLVINFO_EXT_TLV_TYPE_DEV_TYPE;
|
||||
len = sizeof(buf);
|
||||
mem_clear(buf, len);
|
||||
ret = dfd_tlvinfo_get_e2prom_info(eeprom, DFD_E2PROM_MAX_LEN, &tlv_type, buf, &len);
|
||||
if (ret) {
|
||||
DBG_ERROR("dfd_tlvinfo_get_e2prom_info failed ret %d.\n", ret);
|
||||
return -1;
|
||||
}
|
||||
for (ret = 0; ret < 4; ret++) {
|
||||
DBG_DEBUG("buf 0x%02x.\n", buf[ret]);
|
||||
}
|
||||
|
||||
cardtype = ntohl(*((uint32_t *)buf));
|
||||
DBG_DEBUG("cardtype 0x%x.\n", cardtype);
|
||||
return cardtype;
|
||||
}
|
||||
|
||||
static int __dfd_get_my_card_type(void)
|
||||
{
|
||||
return dfd_tlvinfo_get_cardtype();
|
||||
}
|
||||
|
||||
/* Get its own card type */
|
||||
int dfd_get_my_card_type(void)
|
||||
{
|
||||
int type;
|
||||
int cnt;
|
||||
|
||||
if (dfd_my_type != 0) {
|
||||
DBG_DEBUG("my_type = 0x%x\r\n", dfd_my_type);
|
||||
return dfd_my_type;
|
||||
}
|
||||
|
||||
cnt = PLATFORM_CARDTYPE_RETRY_CNT;
|
||||
while (cnt--) {
|
||||
type = __dfd_get_my_card_type();
|
||||
if (type < 0) {
|
||||
RAGILE_COMMON_DEBUG_ERROR("__dfd_get_my_card_type fail cnt %d, ret %d.\n", cnt, type);
|
||||
msleep(PLATFORM_CARDTYPE_RETRY_TIMES);
|
||||
continue;
|
||||
}
|
||||
RAGILE_COMMON_DEBUG_VERBOSE("success to get type 0x%x.\n", type);
|
||||
break;
|
||||
}
|
||||
|
||||
dfd_my_type = type;
|
||||
return dfd_my_type;
|
||||
}
|
||||
EXPORT_SYMBOL(dfd_get_my_card_type);
|
||||
|
||||
static int __init ragile_common_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
RAGILE_COMMON_DEBUG_VERBOSE("Enter.\n");
|
||||
ret = dfd_get_my_card_type();
|
||||
if (ret <= 0) {
|
||||
RAGILE_COMMON_DEBUG_ERROR("dfd_get_my_card_type failed, ret %d.\n", ret);
|
||||
printk(KERN_ERR "Warning: Device type get failed, please check the TLV-EEPROM!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
RAGILE_COMMON_DEBUG_VERBOSE("Leave success type 0x%x.\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ragile_common_exit(void)
|
||||
{
|
||||
RAGILE_COMMON_DEBUG_VERBOSE("Exit.\n");
|
||||
}
|
||||
|
||||
module_init(ragile_common_init);
|
||||
module_exit(ragile_common_exit);
|
||||
|
||||
MODULE_DESCRIPTION("ragile Platform Support");
|
||||
MODULE_AUTHOR("tangjiamiao <support@ragilenetworks.com>");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,79 +0,0 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/platform_data/i2c-gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c-smbus.h>
|
||||
#include <linux/string.h>
|
||||
#include "ragile.h"
|
||||
|
||||
#define PLATFORM_I2C_RETRY_TIMES 3
|
||||
|
||||
s32 platform_i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command)
|
||||
{
|
||||
int try;
|
||||
s32 ret;
|
||||
|
||||
ret = -1;
|
||||
for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try++) {
|
||||
if ((ret = i2c_smbus_read_byte_data(client, command)) >= 0 )
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(platform_i2c_smbus_read_byte_data);
|
||||
|
||||
s32 platform_i2c_smbus_read_i2c_block_data(const struct i2c_client *client,
|
||||
u8 command, u8 length, u8 *values)
|
||||
{
|
||||
int try;
|
||||
s32 ret;
|
||||
|
||||
ret = -1;
|
||||
for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try++) {
|
||||
if ((ret = i2c_smbus_read_i2c_block_data(client, command, length, values)) >= 0 )
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(platform_i2c_smbus_read_i2c_block_data);
|
||||
|
||||
s32 platform_i2c_smbus_read_word_data(const struct i2c_client *client, u8 command)
|
||||
{
|
||||
int try;
|
||||
s32 ret;
|
||||
|
||||
ret = -1;
|
||||
for (try = 0; try < PLATFORM_I2C_RETRY_TIMES; try++) {
|
||||
if ((ret = i2c_smbus_read_word_data(client, command)) >= 0 )
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(platform_i2c_smbus_read_word_data);
|
||||
|
||||
static int __init ragile_platform_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ragile_platform_exit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
module_init(ragile_platform_init);
|
||||
module_exit(ragile_platform_exit);
|
||||
|
||||
MODULE_DESCRIPTION("ragile Platform Support");
|
||||
MODULE_AUTHOR("tangjiamiao <support@ragilenetworks.com>");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,858 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* at24.c - handle most I2C EEPROMs
|
||||
*
|
||||
* Copyright (C) 2005-2007 David Brownell
|
||||
* Copyright (C) 2008 Wolfram Sang, Pengutronix
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/nvmem-provider.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* Address pointer is 16 bit. */
|
||||
#define AT24_FLAG_ADDR16 BIT(7)
|
||||
/* sysfs-entry will be read-only. */
|
||||
#define AT24_FLAG_READONLY BIT(6)
|
||||
/* sysfs-entry will be world-readable. */
|
||||
#define AT24_FLAG_IRUGO BIT(5)
|
||||
/* Take always 8 addresses (24c00). */
|
||||
#define AT24_FLAG_TAKE8ADDR BIT(4)
|
||||
/* Factory-programmed serial number. */
|
||||
#define AT24_FLAG_SERIAL BIT(3)
|
||||
/* Factory-programmed mac address. */
|
||||
#define AT24_FLAG_MAC BIT(2)
|
||||
/* Does not auto-rollover reads to the next slave address. */
|
||||
#define AT24_FLAG_NO_RDROL BIT(1)
|
||||
|
||||
/*
|
||||
* I2C EEPROMs from most vendors are inexpensive and mostly interchangeable.
|
||||
* Differences between different vendor product lines (like Atmel AT24C or
|
||||
* MicroChip 24LC, etc) won't much matter for typical read/write access.
|
||||
* There are also I2C RAM chips, likewise interchangeable. One example
|
||||
* would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes).
|
||||
*
|
||||
* However, misconfiguration can lose data. "Set 16-bit memory address"
|
||||
* to a part with 8-bit addressing will overwrite data. Writing with too
|
||||
* big a page size also loses data. And it's not safe to assume that the
|
||||
* conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC
|
||||
* uses 0x51, for just one example.
|
||||
*
|
||||
* Accordingly, explicit board-specific configuration data should be used
|
||||
* in almost all cases. (One partial exception is an SMBus used to access
|
||||
* "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.)
|
||||
*
|
||||
* So this driver uses "new style" I2C driver binding, expecting to be
|
||||
* told what devices exist. That may be in arch/X/mach-Y/board-Z.c or
|
||||
* similar kernel-resident tables; or, configuration data coming from
|
||||
* a bootloader.
|
||||
*
|
||||
* Other than binding model, current differences from "eeprom" driver are
|
||||
* that this one handles write access and isn't restricted to 24c02 devices.
|
||||
* It also handles larger devices (32 kbit and up) with two-byte addresses,
|
||||
* which won't work on pure SMBus systems.
|
||||
*/
|
||||
|
||||
struct at24_client {
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
struct at24_data {
|
||||
/*
|
||||
* Lock protects against activities from other Linux tasks,
|
||||
* but not from changes by other I2C masters.
|
||||
*/
|
||||
struct mutex lock;
|
||||
|
||||
unsigned int write_max;
|
||||
unsigned int num_addresses;
|
||||
unsigned int offset_adj;
|
||||
|
||||
u32 byte_len;
|
||||
u16 page_size;
|
||||
u8 flags;
|
||||
|
||||
struct nvmem_device *nvmem;
|
||||
struct regulator *vcc_reg;
|
||||
void (*read_post)(unsigned int off, char *buf, size_t count);
|
||||
|
||||
/*
|
||||
* Some chips tie up multiple I2C addresses; dummy devices reserve
|
||||
* them for us, and we'll use them with SMBus calls.
|
||||
*/
|
||||
struct at24_client client[];
|
||||
};
|
||||
|
||||
/*
|
||||
* This parameter is to help this driver avoid blocking other drivers out
|
||||
* of I2C for potentially troublesome amounts of time. With a 100 kHz I2C
|
||||
* clock, one 256 byte read takes about 1/43 second which is excessive;
|
||||
* but the 1/170 second it takes at 400 kHz may be quite reasonable; and
|
||||
* at 1 MHz (Fm+) a 1/430 second delay could easily be invisible.
|
||||
*
|
||||
* This value is forced to be a power of two so that writes align on pages.
|
||||
*/
|
||||
static unsigned int at24_io_limit = 128;
|
||||
module_param_named(io_limit, at24_io_limit, uint, 0);
|
||||
MODULE_PARM_DESC(at24_io_limit, "Maximum bytes per I/O (default 128)");
|
||||
|
||||
/*
|
||||
* Specs often allow 5 msec for a page write, sometimes 20 msec;
|
||||
* it's important to recover from write timeouts.
|
||||
*/
|
||||
static unsigned int at24_write_timeout = 25;
|
||||
module_param_named(write_timeout, at24_write_timeout, uint, 0);
|
||||
MODULE_PARM_DESC(at24_write_timeout, "Time (in ms) to try writes (default 25)");
|
||||
|
||||
struct at24_chip_data {
|
||||
u32 byte_len;
|
||||
u8 flags;
|
||||
void (*read_post)(unsigned int off, char *buf, size_t count);
|
||||
};
|
||||
|
||||
#define AT24_CHIP_DATA(_name, _len, _flags) \
|
||||
static const struct at24_chip_data _name = { \
|
||||
.byte_len = _len, .flags = _flags, \
|
||||
}
|
||||
|
||||
#define AT24_CHIP_DATA_CB(_name, _len, _flags, _read_post) \
|
||||
static const struct at24_chip_data _name = { \
|
||||
.byte_len = _len, .flags = _flags, \
|
||||
.read_post = _read_post, \
|
||||
}
|
||||
|
||||
static void at24_read_post_vaio(unsigned int off, char *buf, size_t count)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (capable(CAP_SYS_ADMIN))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Hide VAIO private settings to regular users:
|
||||
* - BIOS passwords: bytes 0x00 to 0x0f
|
||||
* - UUID: bytes 0x10 to 0x1f
|
||||
* - Serial number: 0xc0 to 0xdf
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
if ((off + i <= 0x1f) ||
|
||||
(off + i >= 0xc0 && off + i <= 0xdf))
|
||||
buf[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* needs 8 addresses as A0-A2 are ignored */
|
||||
AT24_CHIP_DATA(at24_data_24c00, 128 / 8, AT24_FLAG_TAKE8ADDR);
|
||||
/* old variants can't be handled with this generic entry! */
|
||||
AT24_CHIP_DATA(at24_data_24c01, 1024 / 8, 0);
|
||||
AT24_CHIP_DATA(at24_data_24cs01, 16,
|
||||
AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
|
||||
AT24_CHIP_DATA(at24_data_24c02, 2048 / 8, AT24_FLAG_IRUGO);
|
||||
AT24_CHIP_DATA(at24_data_24cs02, 16,
|
||||
AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
|
||||
AT24_CHIP_DATA(at24_data_24mac402, 48 / 8,
|
||||
AT24_FLAG_MAC | AT24_FLAG_READONLY);
|
||||
AT24_CHIP_DATA(at24_data_24mac602, 64 / 8,
|
||||
AT24_FLAG_MAC | AT24_FLAG_READONLY);
|
||||
/* spd is a 24c02 in memory DIMMs */
|
||||
AT24_CHIP_DATA(at24_data_spd, 2048 / 8,
|
||||
AT24_FLAG_READONLY | AT24_FLAG_IRUGO);
|
||||
/* 24c02_vaio is a 24c02 on some Sony laptops */
|
||||
AT24_CHIP_DATA_CB(at24_data_24c02_vaio, 2048 / 8,
|
||||
AT24_FLAG_READONLY | AT24_FLAG_IRUGO,
|
||||
at24_read_post_vaio);
|
||||
AT24_CHIP_DATA(at24_data_24c04, 4096 / 8, 0);
|
||||
AT24_CHIP_DATA(at24_data_24cs04, 16,
|
||||
AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
|
||||
/* 24rf08 quirk is handled at i2c-core */
|
||||
AT24_CHIP_DATA(at24_data_24c08, 8192 / 8, 0);
|
||||
AT24_CHIP_DATA(at24_data_24cs08, 16,
|
||||
AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
|
||||
AT24_CHIP_DATA(at24_data_24c16, 16384 / 8, 0);
|
||||
AT24_CHIP_DATA(at24_data_24cs16, 16,
|
||||
AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
|
||||
AT24_CHIP_DATA(at24_data_24c32, 32768 / 8, AT24_FLAG_ADDR16);
|
||||
AT24_CHIP_DATA(at24_data_24cs32, 16,
|
||||
AT24_FLAG_ADDR16 | AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
|
||||
AT24_CHIP_DATA(at24_data_24c64, 65536 / 8, AT24_FLAG_ADDR16 | AT24_FLAG_IRUGO);
|
||||
AT24_CHIP_DATA(at24_data_24cs64, 16,
|
||||
AT24_FLAG_ADDR16 | AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
|
||||
AT24_CHIP_DATA(at24_data_24c128, 131072 / 8, AT24_FLAG_ADDR16);
|
||||
AT24_CHIP_DATA(at24_data_24c256, 262144 / 8, AT24_FLAG_ADDR16);
|
||||
AT24_CHIP_DATA(at24_data_24c512, 524288 / 8, AT24_FLAG_ADDR16);
|
||||
AT24_CHIP_DATA(at24_data_24c1024, 1048576 / 8, AT24_FLAG_ADDR16);
|
||||
AT24_CHIP_DATA(at24_data_24c2048, 2097152 / 8, AT24_FLAG_ADDR16);
|
||||
/* identical to 24c08 ? */
|
||||
AT24_CHIP_DATA(at24_data_INT3499, 8192 / 8, 0);
|
||||
|
||||
static const struct i2c_device_id at24_ids[] = {
|
||||
{ "rg_24c00", (kernel_ulong_t)&at24_data_24c00 },
|
||||
{ "rg_24c01", (kernel_ulong_t)&at24_data_24c01 },
|
||||
{ "rg_24cs01", (kernel_ulong_t)&at24_data_24cs01 },
|
||||
{ "rg_24c02", (kernel_ulong_t)&at24_data_24c02 },
|
||||
{ "rg_24cs02", (kernel_ulong_t)&at24_data_24cs02 },
|
||||
{ "rg_24mac402", (kernel_ulong_t)&at24_data_24mac402 },
|
||||
{ "rg_24mac602", (kernel_ulong_t)&at24_data_24mac602 },
|
||||
{ "rg_spd", (kernel_ulong_t)&at24_data_spd },
|
||||
{ "rg_24c02-vaio", (kernel_ulong_t)&at24_data_24c02_vaio },
|
||||
{ "rg_24c04", (kernel_ulong_t)&at24_data_24c04 },
|
||||
{ "rg_24cs04", (kernel_ulong_t)&at24_data_24cs04 },
|
||||
{ "rg_24c08", (kernel_ulong_t)&at24_data_24c08 },
|
||||
{ "rg_24cs08", (kernel_ulong_t)&at24_data_24cs08 },
|
||||
{ "rg_24c16", (kernel_ulong_t)&at24_data_24c16 },
|
||||
{ "rg_24cs16", (kernel_ulong_t)&at24_data_24cs16 },
|
||||
{ "rg_24c32", (kernel_ulong_t)&at24_data_24c32 },
|
||||
{ "rg_24cs32", (kernel_ulong_t)&at24_data_24cs32 },
|
||||
{ "rg_24c64", (kernel_ulong_t)&at24_data_24c64 },
|
||||
{ "rg_24cs64", (kernel_ulong_t)&at24_data_24cs64 },
|
||||
{ "rg_24c128", (kernel_ulong_t)&at24_data_24c128 },
|
||||
{ "rg_24c256", (kernel_ulong_t)&at24_data_24c256 },
|
||||
{ "rg_24c512", (kernel_ulong_t)&at24_data_24c512 },
|
||||
{ "rg_24c1024", (kernel_ulong_t)&at24_data_24c1024 },
|
||||
{ "rg_24c2048", (kernel_ulong_t)&at24_data_24c2048 },
|
||||
{ "rg_at24", 0 },
|
||||
{ /* END OF LIST */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, at24_ids);
|
||||
|
||||
static const struct of_device_id at24_of_match[] = {
|
||||
{ .compatible = "atmel,24c00", .data = &at24_data_24c00 },
|
||||
{ .compatible = "atmel,24c01", .data = &at24_data_24c01 },
|
||||
{ .compatible = "atmel,24cs01", .data = &at24_data_24cs01 },
|
||||
{ .compatible = "atmel,24c02", .data = &at24_data_24c02 },
|
||||
{ .compatible = "atmel,24cs02", .data = &at24_data_24cs02 },
|
||||
{ .compatible = "atmel,24mac402", .data = &at24_data_24mac402 },
|
||||
{ .compatible = "atmel,24mac602", .data = &at24_data_24mac602 },
|
||||
{ .compatible = "atmel,spd", .data = &at24_data_spd },
|
||||
{ .compatible = "atmel,24c04", .data = &at24_data_24c04 },
|
||||
{ .compatible = "atmel,24cs04", .data = &at24_data_24cs04 },
|
||||
{ .compatible = "atmel,24c08", .data = &at24_data_24c08 },
|
||||
{ .compatible = "atmel,24cs08", .data = &at24_data_24cs08 },
|
||||
{ .compatible = "atmel,24c16", .data = &at24_data_24c16 },
|
||||
{ .compatible = "atmel,24cs16", .data = &at24_data_24cs16 },
|
||||
{ .compatible = "atmel,24c32", .data = &at24_data_24c32 },
|
||||
{ .compatible = "atmel,24cs32", .data = &at24_data_24cs32 },
|
||||
{ .compatible = "atmel,24c64", .data = &at24_data_24c64 },
|
||||
{ .compatible = "atmel,24cs64", .data = &at24_data_24cs64 },
|
||||
{ .compatible = "atmel,24c128", .data = &at24_data_24c128 },
|
||||
{ .compatible = "atmel,24c256", .data = &at24_data_24c256 },
|
||||
{ .compatible = "atmel,24c512", .data = &at24_data_24c512 },
|
||||
{ .compatible = "atmel,24c1024", .data = &at24_data_24c1024 },
|
||||
{ .compatible = "atmel,24c2048", .data = &at24_data_24c2048 },
|
||||
{ /* END OF LIST */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, at24_of_match);
|
||||
|
||||
static const struct acpi_device_id __maybe_unused at24_acpi_ids[] = {
|
||||
{ "INT3499", (kernel_ulong_t)&at24_data_INT3499 },
|
||||
{ "TPF0001", (kernel_ulong_t)&at24_data_24c1024 },
|
||||
{ /* END OF LIST */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
|
||||
|
||||
/*
|
||||
* This routine supports chips which consume multiple I2C addresses. It
|
||||
* computes the addressing information to be used for a given r/w request.
|
||||
* Assumes that sanity checks for offset happened at sysfs-layer.
|
||||
*
|
||||
* Slave address and byte offset derive from the offset. Always
|
||||
* set the byte address; on a multi-master board, another master
|
||||
* may have changed the chip's "current" address pointer.
|
||||
*/
|
||||
static struct at24_client *at24_translate_offset(struct at24_data *at24,
|
||||
unsigned int *offset)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (at24->flags & AT24_FLAG_ADDR16) {
|
||||
i = *offset >> 16;
|
||||
*offset &= 0xffff;
|
||||
} else {
|
||||
i = *offset >> 8;
|
||||
*offset &= 0xff;
|
||||
}
|
||||
|
||||
return &at24->client[i];
|
||||
}
|
||||
|
||||
static struct device *at24_base_client_dev(struct at24_data *at24)
|
||||
{
|
||||
return &at24->client[0].client->dev;
|
||||
}
|
||||
|
||||
static size_t at24_adjust_read_count(struct at24_data *at24,
|
||||
unsigned int offset, size_t count)
|
||||
{
|
||||
unsigned int bits;
|
||||
size_t remainder;
|
||||
|
||||
/*
|
||||
* In case of multi-address chips that don't rollover reads to
|
||||
* the next slave address: truncate the count to the slave boundary,
|
||||
* so that the read never straddles slaves.
|
||||
*/
|
||||
if (at24->flags & AT24_FLAG_NO_RDROL) {
|
||||
bits = (at24->flags & AT24_FLAG_ADDR16) ? 16 : 8;
|
||||
remainder = BIT(bits) - offset;
|
||||
if (count > remainder)
|
||||
count = remainder;
|
||||
}
|
||||
|
||||
if (count > at24_io_limit)
|
||||
count = at24_io_limit;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t at24_regmap_read(struct at24_data *at24, char *buf,
|
||||
unsigned int offset, size_t count)
|
||||
{
|
||||
unsigned long timeout, read_time;
|
||||
struct at24_client *at24_client;
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
at24_client = at24_translate_offset(at24, &offset);
|
||||
regmap = at24_client->regmap;
|
||||
client = at24_client->client;
|
||||
count = at24_adjust_read_count(at24, offset, count);
|
||||
|
||||
/* adjust offset for mac and serial read ops */
|
||||
offset += at24->offset_adj;
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(at24_write_timeout);
|
||||
do {
|
||||
/*
|
||||
* The timestamp shall be taken before the actual operation
|
||||
* to avoid a premature timeout in case of high CPU load.
|
||||
*/
|
||||
read_time = jiffies;
|
||||
|
||||
ret = regmap_bulk_read(regmap, offset, buf, count);
|
||||
dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
|
||||
count, offset, ret, jiffies);
|
||||
if (!ret)
|
||||
return count;
|
||||
|
||||
usleep_range(1000, 1500);
|
||||
} while (time_before(read_time, timeout));
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that if the hardware write-protect pin is pulled high, the whole
|
||||
* chip is normally write protected. But there are plenty of product
|
||||
* variants here, including OTP fuses and partial chip protect.
|
||||
*
|
||||
* We only use page mode writes; the alternative is sloooow. These routines
|
||||
* write at most one page.
|
||||
*/
|
||||
|
||||
static size_t at24_adjust_write_count(struct at24_data *at24,
|
||||
unsigned int offset, size_t count)
|
||||
{
|
||||
unsigned int next_page;
|
||||
|
||||
/* write_max is at most a page */
|
||||
if (count > at24->write_max)
|
||||
count = at24->write_max;
|
||||
|
||||
/* Never roll over backwards, to the start of this page */
|
||||
next_page = roundup(offset + 1, at24->page_size);
|
||||
if (offset + count > next_page)
|
||||
count = next_page - offset;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t at24_regmap_write(struct at24_data *at24, const char *buf,
|
||||
unsigned int offset, size_t count)
|
||||
{
|
||||
unsigned long timeout, write_time;
|
||||
struct at24_client *at24_client;
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
at24_client = at24_translate_offset(at24, &offset);
|
||||
regmap = at24_client->regmap;
|
||||
client = at24_client->client;
|
||||
count = at24_adjust_write_count(at24, offset, count);
|
||||
timeout = jiffies + msecs_to_jiffies(at24_write_timeout);
|
||||
|
||||
do {
|
||||
/*
|
||||
* The timestamp shall be taken before the actual operation
|
||||
* to avoid a premature timeout in case of high CPU load.
|
||||
*/
|
||||
write_time = jiffies;
|
||||
|
||||
ret = regmap_bulk_write(regmap, offset, buf, count);
|
||||
dev_dbg(&client->dev, "write %zu@%d --> %d (%ld)\n",
|
||||
count, offset, ret, jiffies);
|
||||
if (!ret)
|
||||
return count;
|
||||
|
||||
usleep_range(1000, 1500);
|
||||
} while (time_before(write_time, timeout));
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int at24_read(void *priv, unsigned int off, void *val, size_t count)
|
||||
{
|
||||
struct at24_data *at24;
|
||||
struct device *dev;
|
||||
char *buf = val;
|
||||
int i, ret;
|
||||
|
||||
at24 = priv;
|
||||
dev = at24_base_client_dev(at24);
|
||||
|
||||
if (unlikely(!count))
|
||||
return count;
|
||||
|
||||
if (off + count > at24->byte_len)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_noidle(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read data from chip, protecting against concurrent updates
|
||||
* from this host, but not from other I2C masters.
|
||||
*/
|
||||
mutex_lock(&at24->lock);
|
||||
|
||||
for (i = 0; count; i += ret, count -= ret) {
|
||||
ret = at24_regmap_read(at24, buf + i, off + i, count);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&at24->lock);
|
||||
pm_runtime_put(dev);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&at24->lock);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
if (unlikely(at24->read_post))
|
||||
at24->read_post(off, buf, i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at24_write(void *priv, unsigned int off, void *val, size_t count)
|
||||
{
|
||||
struct at24_data *at24;
|
||||
struct device *dev;
|
||||
char *buf = val;
|
||||
int ret;
|
||||
|
||||
at24 = priv;
|
||||
dev = at24_base_client_dev(at24);
|
||||
|
||||
if (unlikely(!count))
|
||||
return -EINVAL;
|
||||
|
||||
if (off + count > at24->byte_len)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_noidle(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to chip, protecting against concurrent updates
|
||||
* from this host, but not from other I2C masters.
|
||||
*/
|
||||
mutex_lock(&at24->lock);
|
||||
|
||||
while (count) {
|
||||
ret = at24_regmap_write(at24, buf, off, count);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&at24->lock);
|
||||
pm_runtime_put(dev);
|
||||
return ret;
|
||||
}
|
||||
buf += ret;
|
||||
off += ret;
|
||||
count -= ret;
|
||||
}
|
||||
|
||||
mutex_unlock(&at24->lock);
|
||||
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct at24_chip_data *at24_get_chip_data(struct device *dev)
|
||||
{
|
||||
struct device_node *of_node = dev->of_node;
|
||||
const struct at24_chip_data *cdata;
|
||||
const struct i2c_device_id *id;
|
||||
|
||||
id = i2c_match_id(at24_ids, to_i2c_client(dev));
|
||||
|
||||
/*
|
||||
* The I2C core allows OF nodes compatibles to match against the
|
||||
* I2C device ID table as a fallback, so check not only if an OF
|
||||
* node is present but also if it matches an OF device ID entry.
|
||||
*/
|
||||
if (of_node && of_match_device(at24_of_match, dev))
|
||||
cdata = of_device_get_match_data(dev);
|
||||
else if (id)
|
||||
cdata = (void *)id->driver_data;
|
||||
else
|
||||
cdata = acpi_device_get_match_data(dev);
|
||||
|
||||
if (!cdata)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
return cdata;
|
||||
}
|
||||
|
||||
static int at24_make_dummy_client(struct at24_data *at24, unsigned int index,
|
||||
struct regmap_config *regmap_config)
|
||||
{
|
||||
struct i2c_client *base_client, *dummy_client;
|
||||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
|
||||
base_client = at24->client[0].client;
|
||||
dev = &base_client->dev;
|
||||
|
||||
dummy_client = devm_i2c_new_dummy_device(dev, base_client->adapter,
|
||||
base_client->addr + index);
|
||||
if (IS_ERR(dummy_client))
|
||||
return PTR_ERR(dummy_client);
|
||||
|
||||
regmap = devm_regmap_init_i2c(dummy_client, regmap_config);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
at24->client[index].client = dummy_client;
|
||||
at24->client[index].regmap = regmap;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int at24_get_offset_adj(u8 flags, unsigned int byte_len)
|
||||
{
|
||||
if (flags & AT24_FLAG_MAC) {
|
||||
/* EUI-48 starts from 0x9a, EUI-64 from 0x98 */
|
||||
return 0xa0 - byte_len;
|
||||
} else if (flags & AT24_FLAG_SERIAL && flags & AT24_FLAG_ADDR16) {
|
||||
/*
|
||||
* For 16 bit address pointers, the word address must contain
|
||||
* a '10' sequence in bits 11 and 10 regardless of the
|
||||
* intended position of the address pointer.
|
||||
*/
|
||||
return 0x0800;
|
||||
} else if (flags & AT24_FLAG_SERIAL) {
|
||||
/*
|
||||
* Otherwise the word address must begin with a '10' sequence,
|
||||
* regardless of the intended address.
|
||||
*/
|
||||
return 0x0080;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int at24_probe(struct i2c_client *client)
|
||||
{
|
||||
struct regmap_config regmap_config = { };
|
||||
struct nvmem_config nvmem_config = { };
|
||||
u32 byte_len, page_size, flags, addrw;
|
||||
const struct at24_chip_data *cdata;
|
||||
struct device *dev = &client->dev;
|
||||
bool i2c_fn_i2c, i2c_fn_block;
|
||||
unsigned int i, num_addresses;
|
||||
struct at24_data *at24;
|
||||
struct regmap *regmap;
|
||||
bool writable;
|
||||
u8 test_byte;
|
||||
int err;
|
||||
|
||||
i2c_fn_i2c = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
|
||||
i2c_fn_block = i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK);
|
||||
|
||||
cdata = at24_get_chip_data(dev);
|
||||
if (IS_ERR(cdata))
|
||||
return PTR_ERR(cdata);
|
||||
|
||||
err = device_property_read_u32(dev, "pagesize", &page_size);
|
||||
if (err)
|
||||
/*
|
||||
* This is slow, but we can't know all eeproms, so we better
|
||||
* play safe. Specifying custom eeprom-types via device tree
|
||||
* or properties is recommended anyhow.
|
||||
*/
|
||||
page_size = 1;
|
||||
|
||||
flags = cdata->flags;
|
||||
if (device_property_present(dev, "read-only"))
|
||||
flags |= AT24_FLAG_READONLY;
|
||||
if (device_property_present(dev, "no-read-rollover"))
|
||||
flags |= AT24_FLAG_NO_RDROL;
|
||||
|
||||
err = device_property_read_u32(dev, "address-width", &addrw);
|
||||
if (!err) {
|
||||
switch (addrw) {
|
||||
case 8:
|
||||
if (flags & AT24_FLAG_ADDR16)
|
||||
dev_warn(dev,
|
||||
"Override address width to be 8, while default is 16\n");
|
||||
flags &= ~AT24_FLAG_ADDR16;
|
||||
break;
|
||||
case 16:
|
||||
flags |= AT24_FLAG_ADDR16;
|
||||
break;
|
||||
default:
|
||||
dev_warn(dev, "Bad \"address-width\" property: %u\n",
|
||||
addrw);
|
||||
}
|
||||
}
|
||||
|
||||
err = device_property_read_u32(dev, "size", &byte_len);
|
||||
if (err)
|
||||
byte_len = cdata->byte_len;
|
||||
|
||||
if (!i2c_fn_i2c && !i2c_fn_block)
|
||||
page_size = 1;
|
||||
|
||||
if (!page_size) {
|
||||
dev_err(dev, "page_size must not be 0!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!is_power_of_2(page_size))
|
||||
dev_warn(dev, "page_size looks suspicious (no power of 2)!\n");
|
||||
|
||||
err = device_property_read_u32(dev, "num-addresses", &num_addresses);
|
||||
if (err) {
|
||||
if (flags & AT24_FLAG_TAKE8ADDR)
|
||||
num_addresses = 8;
|
||||
else
|
||||
num_addresses = DIV_ROUND_UP(byte_len,
|
||||
(flags & AT24_FLAG_ADDR16) ? 65536 : 256);
|
||||
}
|
||||
|
||||
if ((flags & AT24_FLAG_SERIAL) && (flags & AT24_FLAG_MAC)) {
|
||||
dev_err(dev,
|
||||
"invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regmap_config.val_bits = 8;
|
||||
regmap_config.reg_bits = (flags & AT24_FLAG_ADDR16) ? 16 : 8;
|
||||
regmap_config.disable_locking = true;
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, ®map_config);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
at24 = devm_kzalloc(dev, struct_size(at24, client, num_addresses),
|
||||
GFP_KERNEL);
|
||||
if (!at24)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&at24->lock);
|
||||
at24->byte_len = byte_len;
|
||||
at24->page_size = page_size;
|
||||
at24->flags = flags;
|
||||
at24->read_post = cdata->read_post;
|
||||
at24->num_addresses = num_addresses;
|
||||
at24->offset_adj = at24_get_offset_adj(flags, byte_len);
|
||||
at24->client[0].client = client;
|
||||
at24->client[0].regmap = regmap;
|
||||
|
||||
at24->vcc_reg = devm_regulator_get(dev, "vcc");
|
||||
if (IS_ERR(at24->vcc_reg))
|
||||
return PTR_ERR(at24->vcc_reg);
|
||||
|
||||
writable = !(flags & AT24_FLAG_READONLY);
|
||||
if (writable) {
|
||||
at24->write_max = min_t(unsigned int,
|
||||
page_size, at24_io_limit);
|
||||
if (!i2c_fn_i2c && at24->write_max > I2C_SMBUS_BLOCK_MAX)
|
||||
at24->write_max = I2C_SMBUS_BLOCK_MAX;
|
||||
}
|
||||
|
||||
/* use dummy devices for multiple-address chips */
|
||||
for (i = 1; i < num_addresses; i++) {
|
||||
err = at24_make_dummy_client(at24, i, ®map_config);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the 'label' property is not present for the AT24 EEPROM,
|
||||
* then nvmem_config.id is initialised to NVMEM_DEVID_AUTO,
|
||||
* and this will append the 'devid' to the name of the NVMEM
|
||||
* device. This is purely legacy and the AT24 driver has always
|
||||
* defaulted to this. However, if the 'label' property is
|
||||
*/
|
||||
nvmem_config.id = NVMEM_DEVID_AUTO;
|
||||
|
||||
if (device_property_present(dev, "label")) {
|
||||
err = device_property_read_string(dev, "label",
|
||||
&nvmem_config.name);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
nvmem_config.name = dev_name(dev);
|
||||
}
|
||||
|
||||
nvmem_config.type = NVMEM_TYPE_EEPROM;
|
||||
nvmem_config.dev = dev;
|
||||
nvmem_config.read_only = !writable;
|
||||
nvmem_config.root_only = !(flags & AT24_FLAG_IRUGO);
|
||||
nvmem_config.owner = THIS_MODULE;
|
||||
nvmem_config.compat = true;
|
||||
nvmem_config.base_dev = dev;
|
||||
nvmem_config.reg_read = at24_read;
|
||||
nvmem_config.reg_write = at24_write;
|
||||
nvmem_config.priv = at24;
|
||||
nvmem_config.stride = 1;
|
||||
nvmem_config.word_size = 1;
|
||||
nvmem_config.size = byte_len;
|
||||
|
||||
i2c_set_clientdata(client, at24);
|
||||
|
||||
err = regulator_enable(at24->vcc_reg);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to enable vcc regulator\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* enable runtime pm */
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
|
||||
if (IS_ERR(at24->nvmem)) {
|
||||
pm_runtime_disable(dev);
|
||||
if (!pm_runtime_status_suspended(dev))
|
||||
regulator_disable(at24->vcc_reg);
|
||||
return PTR_ERR(at24->nvmem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a one-byte test read to verify that the
|
||||
* chip is functional.
|
||||
*/
|
||||
err = at24_read(at24, 0, &test_byte, 1);
|
||||
if (err) {
|
||||
pm_runtime_disable(dev);
|
||||
if (!pm_runtime_status_suspended(dev))
|
||||
regulator_disable(at24->vcc_reg);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pm_runtime_idle(dev);
|
||||
|
||||
if (writable)
|
||||
dev_info(dev, "%u byte %s EEPROM, writable, %u bytes/write\n",
|
||||
byte_len, client->name, at24->write_max);
|
||||
else
|
||||
dev_info(dev, "%u byte %s EEPROM, read-only\n",
|
||||
byte_len, client->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at24_remove(struct i2c_client *client)
|
||||
{
|
||||
struct at24_data *at24 = i2c_get_clientdata(client);
|
||||
|
||||
pm_runtime_disable(&client->dev);
|
||||
if (!pm_runtime_status_suspended(&client->dev))
|
||||
regulator_disable(at24->vcc_reg);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused at24_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct at24_data *at24 = i2c_get_clientdata(client);
|
||||
|
||||
return regulator_disable(at24->vcc_reg);
|
||||
}
|
||||
|
||||
static int __maybe_unused at24_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct at24_data *at24 = i2c_get_clientdata(client);
|
||||
|
||||
return regulator_enable(at24->vcc_reg);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops at24_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_RUNTIME_PM_OPS(at24_suspend, at24_resume, NULL)
|
||||
};
|
||||
|
||||
static struct i2c_driver at24_driver = {
|
||||
.driver = {
|
||||
.name = "rg_at24",
|
||||
.pm = &at24_pm_ops,
|
||||
.of_match_table = at24_of_match,
|
||||
.acpi_match_table = ACPI_PTR(at24_acpi_ids),
|
||||
},
|
||||
.probe_new = at24_probe,
|
||||
.remove = at24_remove,
|
||||
.id_table = at24_ids,
|
||||
};
|
||||
|
||||
static int __init at24_init(void)
|
||||
{
|
||||
if (!at24_io_limit) {
|
||||
pr_err("at24: at24_io_limit must not be 0!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
at24_io_limit = rounddown_pow_of_two(at24_io_limit);
|
||||
return i2c_add_driver(&at24_driver);
|
||||
}
|
||||
module_init(at24_init);
|
||||
|
||||
static void __exit at24_exit(void)
|
||||
{
|
||||
i2c_del_driver(&at24_driver);
|
||||
}
|
||||
module_exit(at24_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Driver for most I2C EEPROMs");
|
||||
MODULE_AUTHOR("David Brownell and Wolfram Sang");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* EEPROMs access control driver for display configuration EEPROMs
|
||||
* on DigsyMTC board.
|
||||
*
|
||||
* (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi_gpio.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/spi/eeprom.h>
|
||||
#include <linux/spi/flash.h>
|
||||
|
||||
#define GPIO_TPM_CLK 496
|
||||
#define GPIO_TPM_CS 500
|
||||
#define GPIO_TPM_DI 499
|
||||
#define GPIO_TPM_DO 498
|
||||
|
||||
#define EE_SPI_BUS_NUM 1
|
||||
|
||||
static struct spi_gpio_platform_data tpm_spi_gpio_data = {
|
||||
.sck = GPIO_TPM_CLK,
|
||||
.mosi = GPIO_TPM_DI,
|
||||
.miso = GPIO_TPM_DO,
|
||||
.num_chipselect = 2,
|
||||
};
|
||||
|
||||
static void spi_gpio_release(struct device *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
static struct platform_device tpm_device = {
|
||||
.name = "spi_gpio",
|
||||
.id = 3,
|
||||
.dev = {
|
||||
.platform_data = &tpm_spi_gpio_data,
|
||||
.release = spi_gpio_release,
|
||||
}
|
||||
};
|
||||
|
||||
static struct spi_board_info tpm_info = {
|
||||
.modalias = "tpm_tis_spi",
|
||||
.max_speed_hz = 1000000,
|
||||
.bus_num = 3,
|
||||
.chip_select = 0, /* 0 ,1 */
|
||||
.mode = SPI_MODE_0,
|
||||
.controller_data = (void *)GPIO_TPM_CS,
|
||||
};
|
||||
|
||||
static int __init tpm_devices_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct spi_master *master;
|
||||
|
||||
ret = platform_device_register(&tpm_device);
|
||||
if (ret) {
|
||||
printk("can't add spi-gpio device \n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
master = spi_busnum_to_master(tpm_info.bus_num);
|
||||
if( !master ) {
|
||||
return -ENODEV;
|
||||
}
|
||||
printk(KERN_INFO "enter tpm_devices_init. \n");
|
||||
|
||||
spi_new_device(master, &tpm_info);
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
static void __exit tpm_devices_exit(void)
|
||||
{
|
||||
platform_device_unregister(&tpm_device);
|
||||
}
|
||||
|
||||
module_init(tpm_devices_init);
|
||||
module_exit(tpm_devices_exit);
|
||||
|
||||
MODULE_DESCRIPTION("ragile spi gpio device Support");
|
||||
MODULE_AUTHOR("support@ragilenetworks.com");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,258 +0,0 @@
|
||||
/*
|
||||
* An I2C driver for the PCF85063 RTC
|
||||
* Copyright 2014 Rose Technology
|
||||
*
|
||||
* Author: Sren Andersen <san@rosetechnology.dk>
|
||||
* Maintainers: http://www.nslu2-linux.org/
|
||||
*
|
||||
* based on the other drivers in this same directory.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/*
|
||||
* Information for this driver was pulled from the following datasheets.
|
||||
*
|
||||
* http://www.nxp.com/documents/data_sheet/PCF85063A.pdf
|
||||
* http://www.nxp.com/documents/data_sheet/PCF85063TP.pdf
|
||||
*
|
||||
*/
|
||||
|
||||
#define PCF85063_REG_CTRL1 0x00 /* status */
|
||||
#define PCF85063_REG_CTRL1_CAP_SEL BIT(0)
|
||||
#define PCF85063_REG_CTRL1_STOP BIT(5)
|
||||
#define PCF85063_REG_CTRL2 0x01
|
||||
#define PCF85063_REG_CTRL2_COF 0x07
|
||||
#define PCF85063_REG_SC 0x04 /* datetime */
|
||||
#define PCF85063_REG_SC_OS 0x80
|
||||
#define PCF85063_REG_MN 0x05
|
||||
#define PCF85063_REG_HR 0x06
|
||||
#define PCF85063_REG_DM 0x07
|
||||
#define PCF85063_REG_DW 0x08
|
||||
#define PCF85063_REG_MO 0x09
|
||||
#define PCF85063_REG_YR 0x0A
|
||||
#define PCF85063_SR 0x58
|
||||
|
||||
static struct i2c_driver pcf85063_driver;
|
||||
|
||||
static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
|
||||
{
|
||||
s32 ret;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "Failing to stop the clock\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* stop the clock */
|
||||
ret |= PCF85063_REG_CTRL1_STOP;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ret);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "Failing to stop the clock\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
*ctrl1 = ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
|
||||
{
|
||||
s32 ret;
|
||||
|
||||
/* start the clock */
|
||||
ctrl1 &= ~PCF85063_REG_CTRL1_STOP;
|
||||
ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "Failing to start the clock\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
|
||||
{
|
||||
int rc;
|
||||
u8 regs[7];
|
||||
|
||||
/*
|
||||
* while reading, the time/date registers are blocked and not updated
|
||||
* anymore until the access is finished. To not lose a second
|
||||
* event, the access must be finished within one second. So, read all
|
||||
* time/date registers in one turn.
|
||||
*/
|
||||
rc = i2c_smbus_read_i2c_block_data(client, PCF85063_REG_SC,
|
||||
sizeof(regs), regs);
|
||||
if (rc != sizeof(regs)) {
|
||||
dev_err(&client->dev, "date/time register read error\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* if the clock has lost its power it makes no sense to use its time */
|
||||
if (regs[0] & PCF85063_REG_SC_OS) {
|
||||
dev_warn(&client->dev, "Power loss detected, invalid time\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tm->tm_sec = bcd2bin(regs[0] & 0x7F);
|
||||
tm->tm_min = bcd2bin(regs[1] & 0x7F);
|
||||
tm->tm_hour = bcd2bin(regs[2] & 0x3F); /* rtc hr 0-23 */
|
||||
tm->tm_mday = bcd2bin(regs[3] & 0x3F);
|
||||
tm->tm_wday = regs[4] & 0x07;
|
||||
tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */
|
||||
tm->tm_year = bcd2bin(regs[6]);
|
||||
tm->tm_year += 100;
|
||||
|
||||
return rtc_valid_tm(tm);
|
||||
}
|
||||
|
||||
static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
|
||||
{
|
||||
int rc;
|
||||
u8 regs[7];
|
||||
u8 ctrl1;
|
||||
u8 cof;
|
||||
s32 err;
|
||||
|
||||
cof = 0;
|
||||
cof |= PCF85063_REG_CTRL2_COF;
|
||||
if ((tm->tm_year < 100) || (tm->tm_year > 199))
|
||||
return -EINVAL;
|
||||
|
||||
/* reset rtc-pcf85063 */
|
||||
err = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, PCF85063_SR);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Failing to reset rtc-pcf85063\n");
|
||||
return EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* to accurately set the time, reset the divider chain and keep it in
|
||||
* reset state until all time/date registers are written
|
||||
*/
|
||||
rc = pcf85063_stop_clock(client, &ctrl1);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
/* set CTRL1 CAP_SEL is 12.5pF */
|
||||
ctrl1 |= PCF85063_REG_CTRL1_CAP_SEL;
|
||||
err = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Failing to write the PCF85063_REG_CTRL1\n");
|
||||
return -EIO;
|
||||
}
|
||||
/* set CTRL2 CLKOUT is LOW */
|
||||
err = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL2, cof);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Failing to write the PCF85063_REG_CTRL2\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* hours, minutes and seconds */
|
||||
regs[0] = bin2bcd(tm->tm_sec) & 0x7F; /* clear OS flag */
|
||||
|
||||
regs[1] = bin2bcd(tm->tm_min);
|
||||
regs[2] = bin2bcd(tm->tm_hour);
|
||||
|
||||
/* Day of month, 1 - 31 */
|
||||
regs[3] = bin2bcd(tm->tm_mday);
|
||||
|
||||
/* Day, 0 - 6 */
|
||||
regs[4] = tm->tm_wday & 0x07;
|
||||
|
||||
/* month, 1 - 12 */
|
||||
regs[5] = bin2bcd(tm->tm_mon + 1);
|
||||
|
||||
/* year and century */
|
||||
regs[6] = bin2bcd(tm->tm_year - 100);
|
||||
|
||||
/* write all registers at once */
|
||||
rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC,
|
||||
sizeof(regs), regs);
|
||||
if (rc < 0) {
|
||||
dev_err(&client->dev, "date/time register write error\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the control register as a separate action since the size of
|
||||
* the register space is different between the PCF85063TP and
|
||||
* PCF85063A devices. The rollover point can not be used.
|
||||
*/
|
||||
rc = pcf85063_start_clock(client, ctrl1);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
return pcf85063_get_datetime(to_i2c_client(dev), tm);
|
||||
}
|
||||
|
||||
static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
return pcf85063_set_datetime(to_i2c_client(dev), tm);
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops pcf85063_rtc_ops = {
|
||||
.read_time = pcf85063_rtc_read_time,
|
||||
.set_time = pcf85063_rtc_set_time
|
||||
};
|
||||
|
||||
static int pcf85063_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct rtc_device *rtc;
|
||||
|
||||
dev_dbg(&client->dev, "%s\n", __func__);
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||
return -ENODEV;
|
||||
|
||||
rtc = devm_rtc_device_register(&client->dev,
|
||||
pcf85063_driver.driver.name,
|
||||
&pcf85063_rtc_ops, THIS_MODULE);
|
||||
|
||||
rtc->uie_unsupported = 1;
|
||||
|
||||
return PTR_ERR_OR_ZERO(rtc);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id pcf85063_id[] = {
|
||||
{ "rtcpcf85063", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pcf85063_id);
|
||||
|
||||
static const struct of_device_id pcf85063_of_match[] = {
|
||||
{ .compatible = "nxp,rtcpcf85063" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pcf85063_of_match);
|
||||
|
||||
static struct i2c_driver pcf85063_driver = {
|
||||
.driver = {
|
||||
.name = "rtcpcf85063",
|
||||
.of_match_table = of_match_ptr(pcf85063_of_match),
|
||||
},
|
||||
.probe = pcf85063_probe,
|
||||
.id_table = pcf85063_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(pcf85063_driver);
|
||||
|
||||
MODULE_AUTHOR("Sren Andersen <san@rosetechnology.dk>");
|
||||
MODULE_DESCRIPTION("PCF85063 RTC driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Mix this utility code with some glue code to get one of several types of
|
||||
* simple SPI master driver. Two do polled word-at-a-time I/O:
|
||||
*
|
||||
* - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](),
|
||||
* expanding the per-word routines from the inline templates below.
|
||||
*
|
||||
* - Drivers for controllers resembling bare shift registers. Provide
|
||||
* chipselect() and txrx_word[](), with custom setup()/cleanup() methods
|
||||
* that use your controller's clock and chipselect registers.
|
||||
*
|
||||
* Some hardware works well with requests at spi_transfer scope:
|
||||
*
|
||||
* - Drivers leveraging smarter hardware, with fifos or DMA; or for half
|
||||
* duplex (MicroWire) controllers. Provide chipselect() and txrx_bufs(),
|
||||
* and custom setup()/cleanup() methods.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code that knows what GPIO pins do what should have declared four
|
||||
* functions, ideally as inlines, before including this header:
|
||||
*
|
||||
* void setsck(struct spi_device *, int is_on);
|
||||
* void setmosi(struct spi_device *, int is_on);
|
||||
* int getmiso(struct spi_device *);
|
||||
* void spidelay(unsigned);
|
||||
*
|
||||
* setsck()'s is_on parameter is a zero/nonzero boolean.
|
||||
*
|
||||
* setmosi()'s is_on parameter is a zero/nonzero boolean.
|
||||
*
|
||||
* getmiso() is required to return 0 or 1 only. Any other value is invalid
|
||||
* and will result in improper operation.
|
||||
*
|
||||
* A non-inlined routine would call bitbang_txrx_*() routines. The
|
||||
* main loop could easily compile down to a handful of instructions,
|
||||
* especially if the delay is a NOP (to run at peak speed).
|
||||
*
|
||||
* Since this is software, the timings may not be exactly what your board's
|
||||
* chips need ... there may be several reasons you'd need to tweak timings
|
||||
* in these routines, not just to make it faster or slower to match a
|
||||
* particular CPU clock rate.
|
||||
*/
|
||||
|
||||
static inline u32
|
||||
bitbang_txrx_be_cpha0(struct spi_device *spi,
|
||||
unsigned nsecs, unsigned cpol, unsigned flags,
|
||||
u32 word, u8 bits)
|
||||
{
|
||||
/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
|
||||
|
||||
u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
|
||||
/* clock starts at inactive polarity */
|
||||
for (word <<= (32 - bits); likely(bits); bits--) {
|
||||
|
||||
/* setup MSB (to slave) on trailing edge */
|
||||
if ((flags & SPI_MASTER_NO_TX) == 0) {
|
||||
if ((word & (1 << 31)) != oldbit) {
|
||||
setmosi(spi, word & (1 << 31));
|
||||
oldbit = word & (1 << 31);
|
||||
}
|
||||
}
|
||||
spidelay(nsecs); /* T(setup) */
|
||||
|
||||
setsck(spi, !cpol);
|
||||
spidelay(nsecs);
|
||||
|
||||
/* sample MSB (from slave) on leading edge */
|
||||
word <<= 1;
|
||||
if ((flags & SPI_MASTER_NO_RX) == 0)
|
||||
word |= getmiso(spi);
|
||||
setsck(spi, cpol);
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
bitbang_txrx_be_cpha1(struct spi_device *spi,
|
||||
unsigned nsecs, unsigned cpol, unsigned flags,
|
||||
u32 word, u8 bits)
|
||||
{
|
||||
/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
|
||||
|
||||
u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
|
||||
/* clock starts at inactive polarity */
|
||||
for (word <<= (32 - bits); likely(bits); bits--) {
|
||||
|
||||
/* setup MSB (to slave) on leading edge */
|
||||
setsck(spi, !cpol);
|
||||
if ((flags & SPI_MASTER_NO_TX) == 0) {
|
||||
if ((word & (1 << 31)) != oldbit) {
|
||||
setmosi(spi, word & (1 << 31));
|
||||
oldbit = word & (1 << 31);
|
||||
}
|
||||
}
|
||||
spidelay(nsecs); /* T(setup) */
|
||||
|
||||
setsck(spi, cpol);
|
||||
spidelay(nsecs);
|
||||
|
||||
/* sample MSB (from slave) on trailing edge */
|
||||
word <<= 1;
|
||||
if ((flags & SPI_MASTER_NO_RX) == 0)
|
||||
word |= getmiso(spi);
|
||||
}
|
||||
return word;
|
||||
}
|
@ -1,546 +0,0 @@
|
||||
/*
|
||||
* SPI master driver using generic bitbanged GPIO
|
||||
*
|
||||
* Copyright (C) 2006,2008 David Brownell
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
#include <linux/spi/spi_gpio.h>
|
||||
|
||||
/*
|
||||
* This bitbanging SPI master driver should help make systems usable
|
||||
* when a native hardware SPI engine is not available, perhaps because
|
||||
* its driver isn't yet working or because the I/O pins it requires
|
||||
* are used for other purposes.
|
||||
*
|
||||
* platform_device->driver_data ... points to spi_gpio
|
||||
*
|
||||
* spi->controller_state ... reserved for bitbang framework code
|
||||
* spi->controller_data ... holds chipselect GPIO
|
||||
*
|
||||
* spi->master->dev.driver_data ... points to spi_gpio->bitbang
|
||||
*/
|
||||
|
||||
struct spi_gpio {
|
||||
struct spi_bitbang bitbang;
|
||||
struct spi_gpio_platform_data pdata;
|
||||
struct platform_device *pdev;
|
||||
unsigned long cs_gpios[0];
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Because the overhead of going through four GPIO procedure calls
|
||||
* per transferred bit can make performance a problem, this code
|
||||
* is set up so that you can use it in either of two ways:
|
||||
*
|
||||
* - The slow generic way: set up platform_data to hold the GPIO
|
||||
* numbers used for MISO/MOSI/SCK, and issue procedure calls for
|
||||
* each of them. This driver can handle several such busses.
|
||||
*
|
||||
* - The quicker inlined way: only helps with platform GPIO code
|
||||
* that inlines operations for constant GPIOs. This can give
|
||||
* you tight (fast!) inner loops, but each such bus needs a
|
||||
* new driver. You'll define a new C file, with Makefile and
|
||||
* Kconfig support; the C code can be a total of six lines:
|
||||
*
|
||||
* #define DRIVER_NAME "myboard_spi2"
|
||||
* #define SPI_MISO_GPIO 119
|
||||
* #define SPI_MOSI_GPIO 120
|
||||
* #define SPI_SCK_GPIO 121
|
||||
* #define SPI_N_CHIPSEL 4
|
||||
* #include "spi-gpio.c"
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_NAME
|
||||
#define DRIVER_NAME "spi_gpio"
|
||||
|
||||
#define GENERIC_BITBANG /* vs tight inlines */
|
||||
|
||||
/* all functions referencing these symbols must define pdata */
|
||||
#define SPI_MISO_GPIO ((pdata)->miso)
|
||||
#define SPI_MOSI_GPIO ((pdata)->mosi)
|
||||
#define SPI_SCK_GPIO ((pdata)->sck)
|
||||
|
||||
#define SPI_N_CHIPSEL ((pdata)->num_chipselect)
|
||||
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static inline struct spi_gpio *__pure
|
||||
spi_to_spi_gpio(const struct spi_device *spi)
|
||||
{
|
||||
const struct spi_bitbang *bang;
|
||||
struct spi_gpio *spi_gpio;
|
||||
|
||||
bang = spi_master_get_devdata(spi->master);
|
||||
spi_gpio = container_of(bang, struct spi_gpio, bitbang);
|
||||
return spi_gpio;
|
||||
}
|
||||
|
||||
static inline struct spi_gpio_platform_data *__pure
|
||||
spi_to_pdata(const struct spi_device *spi)
|
||||
{
|
||||
return &spi_to_spi_gpio(spi)->pdata;
|
||||
}
|
||||
|
||||
/* this is #defined to avoid unused-variable warnings when inlining */
|
||||
#define pdata spi_to_pdata(spi)
|
||||
|
||||
static inline void setsck(const struct spi_device *spi, int is_on)
|
||||
{
|
||||
gpio_set_value_cansleep(SPI_SCK_GPIO, is_on);
|
||||
}
|
||||
|
||||
static inline void setmosi(const struct spi_device *spi, int is_on)
|
||||
{
|
||||
gpio_set_value_cansleep(SPI_MOSI_GPIO, is_on);
|
||||
}
|
||||
|
||||
static inline int getmiso(const struct spi_device *spi)
|
||||
{
|
||||
return !!gpio_get_value_cansleep(SPI_MISO_GPIO);
|
||||
}
|
||||
|
||||
#undef pdata
|
||||
|
||||
/*
|
||||
* NOTE: this clocks "as fast as we can". It "should" be a function of the
|
||||
* requested device clock. Software overhead means we usually have trouble
|
||||
* reaching even one Mbit/sec (except when we can inline bitops), so for now
|
||||
* we'll just assume we never need additional per-bit slowdowns.
|
||||
*/
|
||||
#define spidelay(nsecs) do {} while (0)
|
||||
|
||||
#include "spi-bitbang-txrx.h"
|
||||
|
||||
/*
|
||||
* These functions can leverage inline expansion of GPIO calls to shrink
|
||||
* costs for a txrx bit, often by factors of around ten (by instruction
|
||||
* count). That is particularly visible for larger word sizes, but helps
|
||||
* even with default 8-bit words.
|
||||
*
|
||||
* REVISIT overheads calling these functions for each word also have
|
||||
* significant performance costs. Having txrx_bufs() calls that inline
|
||||
* the txrx_word() logic would help performance, e.g. on larger blocks
|
||||
* used with flash storage or MMC/SD. There should also be ways to make
|
||||
* GCC be less stupid about reloading registers inside the I/O loops,
|
||||
* even without inlined GPIO calls; __attribute__((hot)) on GCC 4.3?
|
||||
*/
|
||||
|
||||
static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits)
|
||||
{
|
||||
return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
|
||||
}
|
||||
|
||||
static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits)
|
||||
{
|
||||
return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
|
||||
}
|
||||
|
||||
static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits)
|
||||
{
|
||||
return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
|
||||
}
|
||||
|
||||
static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits)
|
||||
{
|
||||
return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions do not call setmosi or getmiso if respective flag
|
||||
* (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to
|
||||
* call when such pin is not present or defined in the controller.
|
||||
* A separate set of callbacks is defined to get highest possible
|
||||
* speed in the generic case (when both MISO and MOSI lines are
|
||||
* available), as optimiser will remove the checks when argument is
|
||||
* constant.
|
||||
*/
|
||||
|
||||
static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits)
|
||||
{
|
||||
unsigned flags = spi->master->flags;
|
||||
return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
|
||||
}
|
||||
|
||||
static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits)
|
||||
{
|
||||
unsigned flags = spi->master->flags;
|
||||
return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
|
||||
}
|
||||
|
||||
static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits)
|
||||
{
|
||||
unsigned flags = spi->master->flags;
|
||||
return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
|
||||
}
|
||||
|
||||
static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
|
||||
unsigned nsecs, u32 word, u8 bits)
|
||||
{
|
||||
unsigned flags = spi->master->flags;
|
||||
return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
|
||||
{
|
||||
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
|
||||
unsigned long cs = spi_gpio->cs_gpios[spi->chip_select];
|
||||
|
||||
/* set initial clock polarity */
|
||||
if (is_active)
|
||||
setsck(spi, spi->mode & SPI_CPOL);
|
||||
|
||||
if (cs != SPI_GPIO_NO_CHIPSELECT) {
|
||||
/* SPI is normally active-low */
|
||||
gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
|
||||
}
|
||||
}
|
||||
|
||||
static int spi_gpio_setup(struct spi_device *spi)
|
||||
{
|
||||
unsigned long cs;
|
||||
int status = 0;
|
||||
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
|
||||
struct device_node *np = spi->master->dev.of_node;
|
||||
|
||||
if (np) {
|
||||
/*
|
||||
* In DT environments, the CS GPIOs have already been
|
||||
* initialized from the "cs-gpios" property of the node.
|
||||
*/
|
||||
cs = spi_gpio->cs_gpios[spi->chip_select];
|
||||
} else {
|
||||
/*
|
||||
* ... otherwise, take it from spi->controller_data
|
||||
*/
|
||||
cs = (uintptr_t) spi->controller_data;
|
||||
}
|
||||
|
||||
if (!spi->controller_state) {
|
||||
if (cs != SPI_GPIO_NO_CHIPSELECT) {
|
||||
status = gpio_request(cs, dev_name(&spi->dev));
|
||||
if (status)
|
||||
return status;
|
||||
status = gpio_direction_output(cs,
|
||||
!(spi->mode & SPI_CS_HIGH));
|
||||
}
|
||||
}
|
||||
if (!status) {
|
||||
/* in case it was initialized from static board data */
|
||||
spi_gpio->cs_gpios[spi->chip_select] = cs;
|
||||
status = spi_bitbang_setup(spi);
|
||||
}
|
||||
|
||||
if (status) {
|
||||
if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT)
|
||||
gpio_free(cs);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void spi_gpio_cleanup(struct spi_device *spi)
|
||||
{
|
||||
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
|
||||
unsigned long cs = spi_gpio->cs_gpios[spi->chip_select];
|
||||
|
||||
if (cs != SPI_GPIO_NO_CHIPSELECT)
|
||||
gpio_free(cs);
|
||||
spi_bitbang_cleanup(spi);
|
||||
}
|
||||
|
||||
static int spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
|
||||
{
|
||||
int value;
|
||||
|
||||
value = gpio_request(pin, label);
|
||||
if (value == 0) {
|
||||
if (is_in)
|
||||
value = gpio_direction_input(pin);
|
||||
else
|
||||
value = gpio_direction_output(pin, 0);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static int spi_gpio_request(struct spi_gpio_platform_data *pdata,
|
||||
const char *label, u16 *res_flags)
|
||||
{
|
||||
int value;
|
||||
|
||||
/* NOTE: SPI_*_GPIO symbols may reference "pdata" */
|
||||
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI) {
|
||||
value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
|
||||
if (value)
|
||||
goto done;
|
||||
} else {
|
||||
/* HW configuration without MOSI pin */
|
||||
*res_flags |= SPI_MASTER_NO_TX;
|
||||
}
|
||||
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO) {
|
||||
value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
|
||||
if (value)
|
||||
goto free_mosi;
|
||||
} else {
|
||||
/* HW configuration without MISO pin */
|
||||
*res_flags |= SPI_MASTER_NO_RX;
|
||||
}
|
||||
|
||||
value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
|
||||
if (value)
|
||||
goto free_miso;
|
||||
|
||||
goto done;
|
||||
|
||||
free_miso:
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
free_mosi:
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
done:
|
||||
return value;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id spi_gpio_dt_ids[] = {
|
||||
{ .compatible = "spi-gpio" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids);
|
||||
|
||||
static int spi_gpio_probe_dt(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
u32 tmp;
|
||||
struct spi_gpio_platform_data *pdata;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(spi_gpio_dt_ids, &pdev->dev);
|
||||
|
||||
if (!of_id)
|
||||
return 0;
|
||||
|
||||
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_get_named_gpio(np, "gpio-sck", 0);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "gpio-sck property not found\n");
|
||||
goto error_free;
|
||||
}
|
||||
pdata->sck = ret;
|
||||
|
||||
ret = of_get_named_gpio(np, "gpio-miso", 0);
|
||||
if (ret < 0) {
|
||||
dev_info(&pdev->dev, "gpio-miso property not found, switching to no-rx mode\n");
|
||||
pdata->miso = SPI_GPIO_NO_MISO;
|
||||
} else
|
||||
pdata->miso = ret;
|
||||
|
||||
ret = of_get_named_gpio(np, "gpio-mosi", 0);
|
||||
if (ret < 0) {
|
||||
dev_info(&pdev->dev, "gpio-mosi property not found, switching to no-tx mode\n");
|
||||
pdata->mosi = SPI_GPIO_NO_MOSI;
|
||||
} else
|
||||
pdata->mosi = ret;
|
||||
|
||||
ret = of_property_read_u32(np, "num-chipselects", &tmp);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "num-chipselects property not found\n");
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
pdata->num_chipselect = tmp;
|
||||
pdev->dev.platform_data = pdata;
|
||||
|
||||
return 1;
|
||||
|
||||
error_free:
|
||||
devm_kfree(&pdev->dev, pdata);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static inline int spi_gpio_probe_dt(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int spi_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
int status;
|
||||
struct spi_master *master;
|
||||
struct spi_gpio *spi_gpio;
|
||||
struct spi_gpio_platform_data *pdata;
|
||||
u16 master_flags = 0;
|
||||
bool use_of = 0;
|
||||
int num_devices;
|
||||
|
||||
status = spi_gpio_probe_dt(pdev);
|
||||
if (status < 0)
|
||||
return status;
|
||||
if (status > 0)
|
||||
use_of = 1;
|
||||
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
#ifdef GENERIC_BITBANG
|
||||
if (!pdata || (!use_of && !pdata->num_chipselect))
|
||||
return -ENODEV;
|
||||
#endif
|
||||
|
||||
if (use_of && !SPI_N_CHIPSEL)
|
||||
num_devices = 1;
|
||||
else
|
||||
num_devices = SPI_N_CHIPSEL;
|
||||
|
||||
status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio) +
|
||||
(sizeof(unsigned long) * num_devices));
|
||||
if (!master) {
|
||||
status = -ENOMEM;
|
||||
goto gpio_free;
|
||||
}
|
||||
spi_gpio = spi_master_get_devdata(master);
|
||||
platform_set_drvdata(pdev, spi_gpio);
|
||||
|
||||
spi_gpio->pdev = pdev;
|
||||
if (pdata)
|
||||
spi_gpio->pdata = *pdata;
|
||||
|
||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
|
||||
master->flags = master_flags;
|
||||
master->bus_num = pdev->id;
|
||||
master->num_chipselect = num_devices;
|
||||
master->setup = spi_gpio_setup;
|
||||
master->cleanup = spi_gpio_cleanup;
|
||||
#ifdef CONFIG_OF
|
||||
master->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
if (use_of) {
|
||||
int i;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
||||
/*
|
||||
* In DT environments, take the CS GPIO from the "cs-gpios"
|
||||
* property of the node.
|
||||
*/
|
||||
|
||||
if (!SPI_N_CHIPSEL)
|
||||
spi_gpio->cs_gpios[0] = SPI_GPIO_NO_CHIPSELECT;
|
||||
else
|
||||
for (i = 0; i < SPI_N_CHIPSEL; i++) {
|
||||
status = of_get_named_gpio(np, "cs-gpios", i);
|
||||
if (status < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"invalid cs-gpios property\n");
|
||||
goto gpio_free;
|
||||
}
|
||||
spi_gpio->cs_gpios[i] = status;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
spi_gpio->bitbang.master = master;
|
||||
spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
|
||||
|
||||
if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
|
||||
spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
|
||||
spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
|
||||
spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
|
||||
spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
|
||||
} else {
|
||||
spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;
|
||||
spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1;
|
||||
spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2;
|
||||
spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_spec_txrx_word_mode3;
|
||||
}
|
||||
spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
|
||||
spi_gpio->bitbang.flags = SPI_CS_HIGH;
|
||||
|
||||
status = spi_bitbang_start(&spi_gpio->bitbang);
|
||||
if (status < 0) {
|
||||
gpio_free:
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
gpio_free(SPI_SCK_GPIO);
|
||||
spi_master_put(master);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int spi_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_gpio *spi_gpio;
|
||||
struct spi_gpio_platform_data *pdata;
|
||||
|
||||
spi_gpio = platform_get_drvdata(pdev);
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
|
||||
/* stop() unregisters child devices too */
|
||||
spi_bitbang_stop(&spi_gpio->bitbang);
|
||||
|
||||
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
|
||||
gpio_free(SPI_MISO_GPIO);
|
||||
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
|
||||
gpio_free(SPI_MOSI_GPIO);
|
||||
gpio_free(SPI_SCK_GPIO);
|
||||
spi_master_put(spi_gpio->bitbang.master);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
|
||||
static struct platform_driver spi_gpio_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = of_match_ptr(spi_gpio_dt_ids),
|
||||
},
|
||||
.probe = spi_gpio_probe,
|
||||
.remove = spi_gpio_remove,
|
||||
};
|
||||
module_platform_driver(spi_gpio_driver);
|
||||
|
||||
MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO ");
|
||||
MODULE_AUTHOR("David Brownell");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,543 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2004 IBM Corporation
|
||||
* Copyright (C) 2015 Intel Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Leendert van Doorn <leendert@watson.ibm.com>
|
||||
* Dave Safford <safford@watson.ibm.com>
|
||||
* Reiner Sailer <sailer@watson.ibm.com>
|
||||
* Kylene Hall <kjhall@us.ibm.com>
|
||||
*
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||
* Specifications at www.trustedcomputinggroup.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TPM_H__
|
||||
#define __TPM_H__
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/tpm.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/highmem.h>
|
||||
|
||||
enum tpm_const {
|
||||
TPM_MINOR = 224, /* officially assigned */
|
||||
TPM_BUFSIZE = 4096,
|
||||
TPM_NUM_DEVICES = 65536,
|
||||
TPM_RETRY = 50, /* 5 seconds */
|
||||
};
|
||||
|
||||
enum tpm_timeout {
|
||||
TPM_TIMEOUT = 5, /* msecs */
|
||||
TPM_TIMEOUT_RETRY = 100 /* msecs */
|
||||
};
|
||||
|
||||
/* TPM addresses */
|
||||
enum tpm_addr {
|
||||
TPM_SUPERIO_ADDR = 0x2E,
|
||||
TPM_ADDR = 0x4E,
|
||||
};
|
||||
|
||||
/* Indexes the duration array */
|
||||
enum tpm_duration {
|
||||
TPM_SHORT = 0,
|
||||
TPM_MEDIUM = 1,
|
||||
TPM_LONG = 2,
|
||||
TPM_UNDEFINED,
|
||||
};
|
||||
|
||||
#define TPM_WARN_RETRY 0x800
|
||||
#define TPM_WARN_DOING_SELFTEST 0x802
|
||||
#define TPM_ERR_DEACTIVATED 0x6
|
||||
#define TPM_ERR_DISABLED 0x7
|
||||
#define TPM_ERR_INVALID_POSTINIT 38
|
||||
|
||||
#define TPM_HEADER_SIZE 10
|
||||
|
||||
enum tpm2_const {
|
||||
TPM2_PLATFORM_PCR = 24,
|
||||
TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8),
|
||||
TPM2_TIMEOUT_A = 750,
|
||||
TPM2_TIMEOUT_B = 2000,
|
||||
TPM2_TIMEOUT_C = 200,
|
||||
TPM2_TIMEOUT_D = 30,
|
||||
TPM2_DURATION_SHORT = 20,
|
||||
TPM2_DURATION_MEDIUM = 750,
|
||||
TPM2_DURATION_LONG = 2000,
|
||||
};
|
||||
|
||||
enum tpm2_structures {
|
||||
TPM2_ST_NO_SESSIONS = 0x8001,
|
||||
TPM2_ST_SESSIONS = 0x8002,
|
||||
};
|
||||
|
||||
enum tpm2_return_codes {
|
||||
TPM2_RC_HASH = 0x0083, /* RC_FMT1 */
|
||||
TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */
|
||||
TPM2_RC_DISABLED = 0x0120,
|
||||
TPM2_RC_TESTING = 0x090A, /* RC_WARN */
|
||||
};
|
||||
|
||||
enum tpm2_algorithms {
|
||||
TPM2_ALG_SHA1 = 0x0004,
|
||||
TPM2_ALG_KEYEDHASH = 0x0008,
|
||||
TPM2_ALG_SHA256 = 0x000B,
|
||||
TPM2_ALG_SHA384 = 0x000C,
|
||||
TPM2_ALG_SHA512 = 0x000D,
|
||||
TPM2_ALG_NULL = 0x0010,
|
||||
TPM2_ALG_SM3_256 = 0x0012,
|
||||
};
|
||||
|
||||
enum tpm2_command_codes {
|
||||
TPM2_CC_FIRST = 0x011F,
|
||||
TPM2_CC_SELF_TEST = 0x0143,
|
||||
TPM2_CC_STARTUP = 0x0144,
|
||||
TPM2_CC_SHUTDOWN = 0x0145,
|
||||
TPM2_CC_CREATE = 0x0153,
|
||||
TPM2_CC_LOAD = 0x0157,
|
||||
TPM2_CC_UNSEAL = 0x015E,
|
||||
TPM2_CC_FLUSH_CONTEXT = 0x0165,
|
||||
TPM2_CC_GET_CAPABILITY = 0x017A,
|
||||
TPM2_CC_GET_RANDOM = 0x017B,
|
||||
TPM2_CC_PCR_READ = 0x017E,
|
||||
TPM2_CC_PCR_EXTEND = 0x0182,
|
||||
TPM2_CC_LAST = 0x018F,
|
||||
};
|
||||
|
||||
enum tpm2_permanent_handles {
|
||||
TPM2_RS_PW = 0x40000009,
|
||||
};
|
||||
|
||||
enum tpm2_capabilities {
|
||||
TPM2_CAP_TPM_PROPERTIES = 6,
|
||||
};
|
||||
|
||||
enum tpm2_startup_types {
|
||||
TPM2_SU_CLEAR = 0x0000,
|
||||
TPM2_SU_STATE = 0x0001,
|
||||
};
|
||||
|
||||
#define TPM_VID_INTEL 0x8086
|
||||
#define TPM_VID_WINBOND 0x1050
|
||||
#define TPM_VID_STM 0x104A
|
||||
|
||||
#define TPM_PPI_VERSION_LEN 3
|
||||
|
||||
enum tpm_chip_flags {
|
||||
TPM_CHIP_FLAG_REGISTERED = BIT(0),
|
||||
TPM_CHIP_FLAG_TPM2 = BIT(1),
|
||||
TPM_CHIP_FLAG_IRQ = BIT(2),
|
||||
TPM_CHIP_FLAG_VIRTUAL = BIT(3),
|
||||
TPM_CHIP_FLAG_ALWAYS_POWERED = BIT(5),
|
||||
};
|
||||
|
||||
struct tpm_chip {
|
||||
struct device dev;
|
||||
struct cdev cdev;
|
||||
|
||||
/* A driver callback under ops cannot be run unless ops_sem is held
|
||||
* (sometimes implicitly, eg for the sysfs code). ops becomes null
|
||||
* when the driver is unregistered, see tpm_try_get_ops.
|
||||
*/
|
||||
struct rw_semaphore ops_sem;
|
||||
const struct tpm_class_ops *ops;
|
||||
|
||||
unsigned int flags;
|
||||
|
||||
int dev_num; /* /dev/tpm# */
|
||||
unsigned long is_open; /* only one allowed */
|
||||
|
||||
struct mutex tpm_mutex; /* tpm is processing */
|
||||
|
||||
unsigned long timeout_a; /* jiffies */
|
||||
unsigned long timeout_b; /* jiffies */
|
||||
unsigned long timeout_c; /* jiffies */
|
||||
unsigned long timeout_d; /* jiffies */
|
||||
bool timeout_adjusted;
|
||||
unsigned long duration[3]; /* jiffies */
|
||||
bool duration_adjusted;
|
||||
|
||||
struct dentry **bios_dir;
|
||||
|
||||
const struct attribute_group *groups[3];
|
||||
unsigned int groups_cnt;
|
||||
#ifdef CONFIG_ACPI
|
||||
acpi_handle acpi_dev_handle;
|
||||
char ppi_version[TPM_PPI_VERSION_LEN + 1];
|
||||
#endif /* CONFIG_ACPI */
|
||||
};
|
||||
|
||||
#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
|
||||
|
||||
static inline int tpm_read_index(int base, int index)
|
||||
{
|
||||
outb(index, base);
|
||||
return inb(base+1) & 0xFF;
|
||||
}
|
||||
|
||||
static inline void tpm_write_index(int base, int index, int value)
|
||||
{
|
||||
outb(index, base);
|
||||
outb(value & 0xFF, base+1);
|
||||
}
|
||||
struct tpm_input_header {
|
||||
__be16 tag;
|
||||
__be32 length;
|
||||
__be32 ordinal;
|
||||
} __packed;
|
||||
|
||||
struct tpm_output_header {
|
||||
__be16 tag;
|
||||
__be32 length;
|
||||
__be32 return_code;
|
||||
} __packed;
|
||||
|
||||
#define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
|
||||
|
||||
struct stclear_flags_t {
|
||||
__be16 tag;
|
||||
u8 deactivated;
|
||||
u8 disableForceClear;
|
||||
u8 physicalPresence;
|
||||
u8 physicalPresenceLock;
|
||||
u8 bGlobalLock;
|
||||
} __packed;
|
||||
|
||||
struct tpm_version_t {
|
||||
u8 Major;
|
||||
u8 Minor;
|
||||
u8 revMajor;
|
||||
u8 revMinor;
|
||||
} __packed;
|
||||
|
||||
struct tpm_version_1_2_t {
|
||||
__be16 tag;
|
||||
u8 Major;
|
||||
u8 Minor;
|
||||
u8 revMajor;
|
||||
u8 revMinor;
|
||||
} __packed;
|
||||
|
||||
struct timeout_t {
|
||||
__be32 a;
|
||||
__be32 b;
|
||||
__be32 c;
|
||||
__be32 d;
|
||||
} __packed;
|
||||
|
||||
struct duration_t {
|
||||
__be32 tpm_short;
|
||||
__be32 tpm_medium;
|
||||
__be32 tpm_long;
|
||||
} __packed;
|
||||
|
||||
struct permanent_flags_t {
|
||||
__be16 tag;
|
||||
u8 disable;
|
||||
u8 ownership;
|
||||
u8 deactivated;
|
||||
u8 readPubek;
|
||||
u8 disableOwnerClear;
|
||||
u8 allowMaintenance;
|
||||
u8 physicalPresenceLifetimeLock;
|
||||
u8 physicalPresenceHWEnable;
|
||||
u8 physicalPresenceCMDEnable;
|
||||
u8 CEKPUsed;
|
||||
u8 TPMpost;
|
||||
u8 TPMpostLock;
|
||||
u8 FIPS;
|
||||
u8 operator;
|
||||
u8 enableRevokeEK;
|
||||
u8 nvLocked;
|
||||
u8 readSRKPub;
|
||||
u8 tpmEstablished;
|
||||
u8 maintenanceDone;
|
||||
u8 disableFullDALogicInfo;
|
||||
} __packed;
|
||||
|
||||
typedef union {
|
||||
struct permanent_flags_t perm_flags;
|
||||
struct stclear_flags_t stclear_flags;
|
||||
bool owned;
|
||||
__be32 num_pcrs;
|
||||
struct tpm_version_t tpm_version;
|
||||
struct tpm_version_1_2_t tpm_version_1_2;
|
||||
__be32 manufacturer_id;
|
||||
struct timeout_t timeout;
|
||||
struct duration_t duration;
|
||||
} cap_t;
|
||||
|
||||
enum tpm_capabilities {
|
||||
TPM_CAP_FLAG = cpu_to_be32(4),
|
||||
TPM_CAP_PROP = cpu_to_be32(5),
|
||||
CAP_VERSION_1_1 = cpu_to_be32(0x06),
|
||||
CAP_VERSION_1_2 = cpu_to_be32(0x1A)
|
||||
};
|
||||
|
||||
enum tpm_sub_capabilities {
|
||||
TPM_CAP_PROP_PCR = cpu_to_be32(0x101),
|
||||
TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103),
|
||||
TPM_CAP_FLAG_PERM = cpu_to_be32(0x108),
|
||||
TPM_CAP_FLAG_VOL = cpu_to_be32(0x109),
|
||||
TPM_CAP_PROP_OWNER = cpu_to_be32(0x111),
|
||||
TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115),
|
||||
TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120),
|
||||
|
||||
};
|
||||
|
||||
struct tpm_getcap_params_in {
|
||||
__be32 cap;
|
||||
__be32 subcap_size;
|
||||
__be32 subcap;
|
||||
} __packed;
|
||||
|
||||
struct tpm_getcap_params_out {
|
||||
__be32 cap_size;
|
||||
cap_t cap;
|
||||
} __packed;
|
||||
|
||||
struct tpm_readpubek_params_out {
|
||||
u8 algorithm[4];
|
||||
u8 encscheme[2];
|
||||
u8 sigscheme[2];
|
||||
__be32 paramsize;
|
||||
u8 parameters[12]; /*assuming RSA*/
|
||||
__be32 keysize;
|
||||
u8 modulus[256];
|
||||
u8 checksum[20];
|
||||
} __packed;
|
||||
|
||||
typedef union {
|
||||
struct tpm_input_header in;
|
||||
struct tpm_output_header out;
|
||||
} tpm_cmd_header;
|
||||
|
||||
struct tpm_pcrread_out {
|
||||
u8 pcr_result[TPM_DIGEST_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct tpm_pcrread_in {
|
||||
__be32 pcr_idx;
|
||||
} __packed;
|
||||
|
||||
struct tpm_pcrextend_in {
|
||||
__be32 pcr_idx;
|
||||
u8 hash[TPM_DIGEST_SIZE];
|
||||
} __packed;
|
||||
|
||||
/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
|
||||
* bytes, but 128 is still a relatively large number of random bytes and
|
||||
* anything much bigger causes users of struct tpm_cmd_t to start getting
|
||||
* compiler warnings about stack frame size. */
|
||||
#define TPM_MAX_RNG_DATA 128
|
||||
|
||||
struct tpm_getrandom_out {
|
||||
__be32 rng_data_len;
|
||||
u8 rng_data[TPM_MAX_RNG_DATA];
|
||||
} __packed;
|
||||
|
||||
struct tpm_getrandom_in {
|
||||
__be32 num_bytes;
|
||||
} __packed;
|
||||
|
||||
struct tpm_startup_in {
|
||||
__be16 startup_type;
|
||||
} __packed;
|
||||
|
||||
typedef union {
|
||||
struct tpm_getcap_params_out getcap_out;
|
||||
struct tpm_readpubek_params_out readpubek_out;
|
||||
u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)];
|
||||
struct tpm_getcap_params_in getcap_in;
|
||||
struct tpm_pcrread_in pcrread_in;
|
||||
struct tpm_pcrread_out pcrread_out;
|
||||
struct tpm_pcrextend_in pcrextend_in;
|
||||
struct tpm_getrandom_in getrandom_in;
|
||||
struct tpm_getrandom_out getrandom_out;
|
||||
struct tpm_startup_in startup_in;
|
||||
} tpm_cmd_params;
|
||||
|
||||
struct tpm_cmd_t {
|
||||
tpm_cmd_header header;
|
||||
tpm_cmd_params params;
|
||||
} __packed;
|
||||
|
||||
/* A string buffer type for constructing TPM commands. This is based on the
|
||||
* ideas of string buffer code in security/keys/trusted.h but is heap based
|
||||
* in order to keep the stack usage minimal.
|
||||
*/
|
||||
|
||||
enum tpm_buf_flags {
|
||||
TPM_BUF_OVERFLOW = BIT(0),
|
||||
};
|
||||
|
||||
struct tpm_buf {
|
||||
struct page *data_page;
|
||||
unsigned int flags;
|
||||
u8 *data;
|
||||
};
|
||||
|
||||
static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
|
||||
{
|
||||
struct tpm_input_header *head;
|
||||
|
||||
buf->data_page = alloc_page(GFP_HIGHUSER);
|
||||
if (!buf->data_page)
|
||||
return -ENOMEM;
|
||||
|
||||
buf->flags = 0;
|
||||
buf->data = kmap(buf->data_page);
|
||||
|
||||
head = (struct tpm_input_header *) buf->data;
|
||||
|
||||
head->tag = cpu_to_be16(tag);
|
||||
head->length = cpu_to_be32(sizeof(*head));
|
||||
head->ordinal = cpu_to_be32(ordinal);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void tpm_buf_destroy(struct tpm_buf *buf)
|
||||
{
|
||||
kunmap(buf->data_page);
|
||||
__free_page(buf->data_page);
|
||||
}
|
||||
|
||||
static inline u32 tpm_buf_length(struct tpm_buf *buf)
|
||||
{
|
||||
struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
|
||||
|
||||
return be32_to_cpu(head->length);
|
||||
}
|
||||
|
||||
static inline u16 tpm_buf_tag(struct tpm_buf *buf)
|
||||
{
|
||||
struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
|
||||
|
||||
return be16_to_cpu(head->tag);
|
||||
}
|
||||
|
||||
static inline void tpm_buf_append(struct tpm_buf *buf,
|
||||
const unsigned char *new_data,
|
||||
unsigned int new_len)
|
||||
{
|
||||
struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
|
||||
u32 len = tpm_buf_length(buf);
|
||||
|
||||
/* Return silently if overflow has already happened. */
|
||||
if (buf->flags & TPM_BUF_OVERFLOW)
|
||||
return;
|
||||
|
||||
if ((len + new_len) > PAGE_SIZE) {
|
||||
WARN(1, "tpm_buf: overflow\n");
|
||||
buf->flags |= TPM_BUF_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&buf->data[len], new_data, new_len);
|
||||
head->length = cpu_to_be32(len + new_len);
|
||||
}
|
||||
|
||||
static inline void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value)
|
||||
{
|
||||
tpm_buf_append(buf, &value, 1);
|
||||
}
|
||||
|
||||
static inline void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value)
|
||||
{
|
||||
__be16 value2 = cpu_to_be16(value);
|
||||
|
||||
tpm_buf_append(buf, (u8 *) &value2, 2);
|
||||
}
|
||||
|
||||
static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
|
||||
{
|
||||
__be32 value2 = cpu_to_be32(value);
|
||||
|
||||
tpm_buf_append(buf, (u8 *) &value2, 4);
|
||||
}
|
||||
|
||||
extern struct class *tpm_class;
|
||||
extern dev_t tpm_devt;
|
||||
extern const struct file_operations tpm_fops;
|
||||
extern struct idr dev_nums_idr;
|
||||
|
||||
enum tpm_transmit_flags {
|
||||
TPM_TRANSMIT_UNLOCKED = BIT(0),
|
||||
};
|
||||
|
||||
ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
|
||||
unsigned int flags);
|
||||
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, int len,
|
||||
unsigned int flags, const char *desc);
|
||||
ssize_t tpm_getcap(struct tpm_chip *chip, __be32 subcap_id, cap_t *cap,
|
||||
const char *desc);
|
||||
int tpm_get_timeouts(struct tpm_chip *);
|
||||
int tpm1_auto_startup(struct tpm_chip *chip);
|
||||
int tpm_do_selftest(struct tpm_chip *chip);
|
||||
unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
|
||||
int tpm_pm_suspend(struct device *dev);
|
||||
int tpm_pm_resume(struct device *dev);
|
||||
int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
|
||||
wait_queue_head_t *queue, bool check_cancel);
|
||||
|
||||
struct tpm_chip *tpm_chip_find_get(int chip_num);
|
||||
__must_check int tpm_try_get_ops(struct tpm_chip *chip);
|
||||
void tpm_put_ops(struct tpm_chip *chip);
|
||||
|
||||
struct tpm_chip *tpm_chip_alloc(struct device *dev,
|
||||
const struct tpm_class_ops *ops);
|
||||
struct tpm_chip *tpmm_chip_alloc(struct device *pdev,
|
||||
const struct tpm_class_ops *ops);
|
||||
int tpm_chip_register(struct tpm_chip *chip);
|
||||
void tpm_chip_unregister(struct tpm_chip *chip);
|
||||
|
||||
void tpm_sysfs_add_device(struct tpm_chip *chip);
|
||||
|
||||
int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
extern void tpm_add_ppi(struct tpm_chip *chip);
|
||||
#else
|
||||
static inline void tpm_add_ppi(struct tpm_chip *chip)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline inline u32 tpm2_rc_value(u32 rc)
|
||||
{
|
||||
return (rc & BIT(7)) ? rc & 0xff : rc;
|
||||
}
|
||||
|
||||
int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
|
||||
int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
|
||||
int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max);
|
||||
int tpm2_seal_trusted(struct tpm_chip *chip,
|
||||
struct trusted_key_payload *payload,
|
||||
struct trusted_key_options *options);
|
||||
int tpm2_unseal_trusted(struct tpm_chip *chip,
|
||||
struct trusted_key_payload *payload,
|
||||
struct trusted_key_options *options);
|
||||
ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
|
||||
u32 *value, const char *desc);
|
||||
|
||||
int tpm2_auto_startup(struct tpm_chip *chip);
|
||||
void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
|
||||
unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
|
||||
int tpm2_probe(struct tpm_chip *chip);
|
||||
#endif
|
@ -1,855 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005, 2006 IBM Corporation
|
||||
* Copyright (C) 2014, 2015 Intel Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Leendert van Doorn <leendert@watson.ibm.com>
|
||||
* Kylene Hall <kjhall@us.ibm.com>
|
||||
*
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||
* Specifications at www.trustedcomputinggroup.org
|
||||
*
|
||||
* This device driver implements the TPM interface as defined in
|
||||
* the TCG TPM Interface Spec version 1.2, revision 1.0.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/pnp.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/freezer.h>
|
||||
#include "tpm.h"
|
||||
#include "tpm_tis_core.h"
|
||||
|
||||
/* Before we attempt to access the TPM we must see that the valid bit is set.
|
||||
* The specification says that this bit is 0 at reset and remains 0 until the
|
||||
* 'TPM has gone through its self test and initialization and has established
|
||||
* correct values in the other bits.'
|
||||
*/
|
||||
static int wait_startup(struct tpm_chip *chip, int l)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
unsigned long stop = jiffies + chip->timeout_a;
|
||||
|
||||
do {
|
||||
int rc;
|
||||
u8 access;
|
||||
|
||||
rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (access & TPM_ACCESS_VALID)
|
||||
return 0;
|
||||
msleep(TPM_TIMEOUT);
|
||||
} while (time_before(jiffies, stop));
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int check_locality(struct tpm_chip *chip, int l)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
int rc;
|
||||
u8 access;
|
||||
|
||||
rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
|
||||
(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
|
||||
return priv->locality = l;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void release_locality(struct tpm_chip *chip, int l, int force)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
int rc;
|
||||
u8 access;
|
||||
|
||||
rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access);
|
||||
if (rc < 0)
|
||||
return;
|
||||
|
||||
if (force || (access &
|
||||
(TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
|
||||
(TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
|
||||
tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
|
||||
|
||||
}
|
||||
|
||||
static int request_locality(struct tpm_chip *chip, int l)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
unsigned long stop, timeout;
|
||||
long rc;
|
||||
|
||||
if (check_locality(chip, l) >= 0)
|
||||
return l;
|
||||
|
||||
rc = tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_REQUEST_USE);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
stop = jiffies + chip->timeout_a;
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
|
||||
again:
|
||||
timeout = stop - jiffies;
|
||||
if ((long)timeout <= 0)
|
||||
return -1;
|
||||
rc = wait_event_interruptible_timeout(priv->int_queue,
|
||||
(check_locality
|
||||
(chip, l) >= 0),
|
||||
timeout);
|
||||
if (rc > 0)
|
||||
return l;
|
||||
if (rc == -ERESTARTSYS && freezing(current)) {
|
||||
clear_thread_flag(TIF_SIGPENDING);
|
||||
goto again;
|
||||
}
|
||||
} else {
|
||||
/* wait for burstcount */
|
||||
do {
|
||||
if (check_locality(chip, l) >= 0)
|
||||
return l;
|
||||
msleep(TPM_TIMEOUT);
|
||||
} while (time_before(jiffies, stop));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static u8 tpm_tis_status(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
int rc;
|
||||
u8 status;
|
||||
|
||||
rc = tpm_tis_read8(priv, TPM_STS(priv->locality), &status);
|
||||
if (rc < 0)
|
||||
return 0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void tpm_tis_ready(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
|
||||
/* this causes the current command to be aborted */
|
||||
tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_COMMAND_READY);
|
||||
}
|
||||
|
||||
static int get_burstcount(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
unsigned long stop;
|
||||
int burstcnt, rc;
|
||||
u32 value;
|
||||
|
||||
/* wait for burstcount */
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
||||
stop = jiffies + chip->timeout_a;
|
||||
else
|
||||
stop = jiffies + chip->timeout_d;
|
||||
do {
|
||||
rc = tpm_tis_read32(priv, TPM_STS(priv->locality), &value);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
burstcnt = (value >> 8) & 0xFFFF;
|
||||
if (burstcnt)
|
||||
return burstcnt;
|
||||
msleep(TPM_TIMEOUT);
|
||||
} while (time_before(jiffies, stop));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
int size = 0, burstcnt, rc;
|
||||
|
||||
while (size < count &&
|
||||
wait_for_tpm_stat(chip,
|
||||
TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
chip->timeout_c,
|
||||
&priv->read_queue, true) == 0) {
|
||||
burstcnt = get_burstcount(chip);
|
||||
if (burstcnt < 0) {
|
||||
dev_err(&chip->dev, "Unable to read burstcount\n");
|
||||
return burstcnt;
|
||||
}
|
||||
burstcnt = min_t(int, burstcnt, count - size);
|
||||
|
||||
rc = tpm_tis_read_bytes(priv, TPM_DATA_FIFO(priv->locality),
|
||||
burstcnt, buf + size);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
size += burstcnt;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
int size = 0;
|
||||
int status;
|
||||
u32 expected;
|
||||
|
||||
if (count < TPM_HEADER_SIZE) {
|
||||
size = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
size = recv_data(chip, buf, TPM_HEADER_SIZE);
|
||||
/* read first 10 bytes, including tag, paramsize, and result */
|
||||
if (size < TPM_HEADER_SIZE) {
|
||||
dev_err(&chip->dev, "Unable to read header\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
expected = be32_to_cpu(*(__be32 *) (buf + 2));
|
||||
if (expected > count || expected < TPM_HEADER_SIZE) {
|
||||
size = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
size += recv_data(chip, &buf[TPM_HEADER_SIZE],
|
||||
expected - TPM_HEADER_SIZE);
|
||||
if (size < expected) {
|
||||
dev_err(&chip->dev, "Unable to read remainder of result\n");
|
||||
size = -ETIME;
|
||||
goto out;
|
||||
}
|
||||
|
||||
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
|
||||
&priv->int_queue, false);
|
||||
status = tpm_tis_status(chip);
|
||||
if (status & TPM_STS_DATA_AVAIL) { /* retry? */
|
||||
dev_err(&chip->dev, "Error left over data\n");
|
||||
size = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
tpm_tis_ready(chip);
|
||||
release_locality(chip, priv->locality, 0);
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* If interrupts are used (signaled by an irq set in the vendor structure)
|
||||
* tpm.c can skip polling for the data to be available as the interrupt is
|
||||
* waited for here
|
||||
*/
|
||||
static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
int rc, status, burstcnt;
|
||||
size_t count = 0;
|
||||
bool itpm = priv->flags & TPM_TIS_ITPM_POSSIBLE;
|
||||
|
||||
if (request_locality(chip, 0) < 0)
|
||||
return -EBUSY;
|
||||
|
||||
status = tpm_tis_status(chip);
|
||||
if ((status & TPM_STS_COMMAND_READY) == 0) {
|
||||
tpm_tis_ready(chip);
|
||||
if (wait_for_tpm_stat
|
||||
(chip, TPM_STS_COMMAND_READY, chip->timeout_b,
|
||||
&priv->int_queue, false) < 0) {
|
||||
rc = -ETIME;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
while (count < len - 1) {
|
||||
burstcnt = get_burstcount(chip);
|
||||
if (burstcnt < 0) {
|
||||
dev_err(&chip->dev, "Unable to read burstcount\n");
|
||||
rc = burstcnt;
|
||||
goto out_err;
|
||||
}
|
||||
burstcnt = min_t(int, burstcnt, len - count - 1);
|
||||
rc = tpm_tis_write_bytes(priv, TPM_DATA_FIFO(priv->locality),
|
||||
burstcnt, buf + count);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
|
||||
count += burstcnt;
|
||||
|
||||
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
|
||||
&priv->int_queue, false);
|
||||
status = tpm_tis_status(chip);
|
||||
if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
|
||||
rc = -EIO;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
/* write last byte */
|
||||
rc = tpm_tis_write8(priv, TPM_DATA_FIFO(priv->locality), buf[count]);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
|
||||
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
|
||||
&priv->int_queue, false);
|
||||
status = tpm_tis_status(chip);
|
||||
if (!itpm && (status & TPM_STS_DATA_EXPECT) != 0) {
|
||||
rc = -EIO;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
tpm_tis_ready(chip);
|
||||
release_locality(chip, priv->locality, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void disable_interrupts(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
u32 intmask;
|
||||
int rc;
|
||||
|
||||
rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
|
||||
if (rc < 0)
|
||||
intmask = 0;
|
||||
|
||||
intmask &= ~TPM_GLOBAL_INT_ENABLE;
|
||||
rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
|
||||
|
||||
devm_free_irq(chip->dev.parent, priv->irq, chip);
|
||||
priv->irq = 0;
|
||||
chip->flags &= ~TPM_CHIP_FLAG_IRQ;
|
||||
}
|
||||
|
||||
/*
|
||||
* If interrupts are used (signaled by an irq set in the vendor structure)
|
||||
* tpm.c can skip polling for the data to be available as the interrupt is
|
||||
* waited for here
|
||||
*/
|
||||
static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
int rc;
|
||||
u32 ordinal;
|
||||
unsigned long dur;
|
||||
|
||||
rc = tpm_tis_send_data(chip, buf, len);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* go and do it */
|
||||
rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
|
||||
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
||||
dur = tpm2_calc_ordinal_duration(chip, ordinal);
|
||||
else
|
||||
dur = tpm_calc_ordinal_duration(chip, ordinal);
|
||||
|
||||
if (wait_for_tpm_stat
|
||||
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
|
||||
&priv->read_queue, false) < 0) {
|
||||
rc = -ETIME;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
out_err:
|
||||
tpm_tis_ready(chip);
|
||||
release_locality(chip, priv->locality, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
|
||||
{
|
||||
int rc, irq;
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
|
||||
if (!(chip->flags & TPM_CHIP_FLAG_IRQ) || priv->irq_tested)
|
||||
return tpm_tis_send_main(chip, buf, len);
|
||||
|
||||
/* Verify receipt of the expected IRQ */
|
||||
irq = priv->irq;
|
||||
priv->irq = 0;
|
||||
chip->flags &= ~TPM_CHIP_FLAG_IRQ;
|
||||
rc = tpm_tis_send_main(chip, buf, len);
|
||||
priv->irq = irq;
|
||||
chip->flags |= TPM_CHIP_FLAG_IRQ;
|
||||
if (!priv->irq_tested)
|
||||
msleep(1);
|
||||
if (!priv->irq_tested)
|
||||
disable_interrupts(chip);
|
||||
priv->irq_tested = true;
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct tis_vendor_timeout_override {
|
||||
u32 did_vid;
|
||||
unsigned long timeout_us[4];
|
||||
};
|
||||
|
||||
static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = {
|
||||
/* Atmel 3204 */
|
||||
{ 0x32041114, { (TIS_SHORT_TIMEOUT*1000), (TIS_LONG_TIMEOUT*1000),
|
||||
(TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } },
|
||||
};
|
||||
|
||||
static bool tpm_tis_update_timeouts(struct tpm_chip *chip,
|
||||
unsigned long *timeout_cap)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
int i, rc;
|
||||
u32 did_vid;
|
||||
|
||||
rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) {
|
||||
if (vendor_timeout_overrides[i].did_vid != did_vid)
|
||||
continue;
|
||||
memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us,
|
||||
sizeof(vendor_timeout_overrides[i].timeout_us));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Early probing for iTPM with STS_DATA_EXPECT flaw.
|
||||
* Try sending command without itpm flag set and if that
|
||||
* fails, repeat with itpm flag set.
|
||||
*/
|
||||
static int probe_itpm(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
int rc = 0;
|
||||
u8 cmd_getticks[] = {
|
||||
0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
|
||||
0x00, 0x00, 0x00, 0xf1
|
||||
};
|
||||
size_t len = sizeof(cmd_getticks);
|
||||
u16 vendor;
|
||||
|
||||
rc = tpm_tis_read16(priv, TPM_DID_VID(0), &vendor);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* probe only iTPMS */
|
||||
if (vendor != TPM_VID_INTEL)
|
||||
return 0;
|
||||
|
||||
rc = tpm_tis_send_data(chip, cmd_getticks, len);
|
||||
if (rc == 0)
|
||||
goto out;
|
||||
|
||||
tpm_tis_ready(chip);
|
||||
release_locality(chip, priv->locality, 0);
|
||||
|
||||
rc = tpm_tis_send_data(chip, cmd_getticks, len);
|
||||
if (rc == 0) {
|
||||
dev_info(&chip->dev, "Detected an iTPM.\n");
|
||||
rc = 1;
|
||||
} else
|
||||
rc = -EFAULT;
|
||||
|
||||
out:
|
||||
tpm_tis_ready(chip);
|
||||
release_locality(chip, priv->locality, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
|
||||
switch (priv->manufacturer_id) {
|
||||
case TPM_VID_WINBOND:
|
||||
return ((status == TPM_STS_VALID) ||
|
||||
(status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)));
|
||||
case TPM_VID_STM:
|
||||
return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY));
|
||||
default:
|
||||
return (status == TPM_STS_COMMAND_READY);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t tis_int_handler(int dummy, void *dev_id)
|
||||
{
|
||||
struct tpm_chip *chip = dev_id;
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
u32 interrupt;
|
||||
int i, rc;
|
||||
|
||||
rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt);
|
||||
if (rc < 0)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (interrupt == 0)
|
||||
return IRQ_NONE;
|
||||
|
||||
priv->irq_tested = true;
|
||||
if (interrupt & TPM_INTF_DATA_AVAIL_INT)
|
||||
wake_up_interruptible(&priv->read_queue);
|
||||
if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
|
||||
for (i = 0; i < 5; i++)
|
||||
if (check_locality(chip, i) >= 0)
|
||||
break;
|
||||
if (interrupt &
|
||||
(TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
|
||||
TPM_INTF_CMD_READY_INT))
|
||||
wake_up_interruptible(&priv->int_queue);
|
||||
|
||||
/* Clear interrupts handled with TPM_EOI */
|
||||
rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt);
|
||||
if (rc < 0)
|
||||
return IRQ_NONE;
|
||||
|
||||
tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int tpm_tis_gen_interrupt(struct tpm_chip *chip)
|
||||
{
|
||||
const char *desc = "attempting to generate an interrupt";
|
||||
u32 cap2;
|
||||
cap_t cap;
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
||||
return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
|
||||
else
|
||||
return tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc);
|
||||
}
|
||||
|
||||
/* Register the IRQ and issue a command that will cause an interrupt. If an
|
||||
* irq is seen then leave the chip setup for IRQ operation, otherwise reverse
|
||||
* everything and leave in polling mode. Returns 0 on success.
|
||||
*/
|
||||
static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
|
||||
int flags, int irq)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
u8 original_int_vec;
|
||||
int rc;
|
||||
u32 int_status;
|
||||
|
||||
if (devm_request_irq(chip->dev.parent, irq, tis_int_handler, flags,
|
||||
dev_name(&chip->dev), chip) != 0) {
|
||||
dev_info(&chip->dev, "Unable to request irq: %d for probe\n",
|
||||
irq);
|
||||
return -1;
|
||||
}
|
||||
priv->irq = irq;
|
||||
|
||||
rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
|
||||
&original_int_vec);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Clear all existing */
|
||||
rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Turn on */
|
||||
rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
|
||||
intmask | TPM_GLOBAL_INT_ENABLE);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
priv->irq_tested = false;
|
||||
|
||||
/* Generate an interrupt by having the core call through to
|
||||
* tpm_tis_send
|
||||
*/
|
||||
rc = tpm_tis_gen_interrupt(chip);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* tpm_tis_send will either confirm the interrupt is working or it
|
||||
* will call disable_irq which undoes all of the above.
|
||||
*/
|
||||
if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
|
||||
rc = tpm_tis_write8(priv, original_int_vec,
|
||||
TPM_INT_VECTOR(priv->locality));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
|
||||
* do not have ACPI/etc. We typically expect the interrupt to be declared if
|
||||
* present.
|
||||
*/
|
||||
static void tpm_tis_probe_irq(struct tpm_chip *chip, u32 intmask)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
u8 original_int_vec;
|
||||
int i, rc;
|
||||
|
||||
rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
|
||||
&original_int_vec);
|
||||
if (rc < 0)
|
||||
return;
|
||||
|
||||
if (!original_int_vec) {
|
||||
if (IS_ENABLED(CONFIG_X86))
|
||||
for (i = 3; i <= 15; i++)
|
||||
if (!tpm_tis_probe_irq_single(chip, intmask, 0,
|
||||
i))
|
||||
return;
|
||||
} else if (!tpm_tis_probe_irq_single(chip, intmask, 0,
|
||||
original_int_vec))
|
||||
return;
|
||||
}
|
||||
|
||||
void tpm_tis_remove(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
u32 reg = TPM_INT_ENABLE(priv->locality);
|
||||
u32 interrupt;
|
||||
int rc;
|
||||
|
||||
rc = tpm_tis_read32(priv, reg, &interrupt);
|
||||
if (rc < 0)
|
||||
interrupt = 0;
|
||||
|
||||
tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt);
|
||||
release_locality(chip, priv->locality, 1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_tis_remove);
|
||||
|
||||
static const struct tpm_class_ops tpm_tis = {
|
||||
.flags = TPM_OPS_AUTO_STARTUP,
|
||||
.status = tpm_tis_status,
|
||||
.recv = tpm_tis_recv,
|
||||
.send = tpm_tis_send,
|
||||
.cancel = tpm_tis_ready,
|
||||
.update_timeouts = tpm_tis_update_timeouts,
|
||||
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
.req_canceled = tpm_tis_req_canceled,
|
||||
};
|
||||
|
||||
int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
||||
const struct tpm_tis_phy_ops *phy_ops,
|
||||
acpi_handle acpi_dev_handle)
|
||||
{
|
||||
u32 vendor, intfcaps, intmask;
|
||||
u8 rid;
|
||||
int rc, probe;
|
||||
struct tpm_chip *chip;
|
||||
|
||||
chip = tpmm_chip_alloc(dev, &tpm_tis);
|
||||
if (IS_ERR(chip))
|
||||
return PTR_ERR(chip);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
chip->acpi_dev_handle = acpi_dev_handle;
|
||||
#endif
|
||||
|
||||
/* Maximum timeouts */
|
||||
chip->timeout_a = msecs_to_jiffies(TIS_TIMEOUT_A_MAX);
|
||||
chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX);
|
||||
chip->timeout_c = msecs_to_jiffies(TIS_TIMEOUT_C_MAX);
|
||||
chip->timeout_d = msecs_to_jiffies(TIS_TIMEOUT_D_MAX);
|
||||
priv->phy_ops = phy_ops;
|
||||
dev_set_drvdata(&chip->dev, priv);
|
||||
|
||||
if (wait_startup(chip, 0) != 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* Take control of the TPM's interrupt hardware and shut it off */
|
||||
rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
|
||||
intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
|
||||
TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
|
||||
intmask &= ~TPM_GLOBAL_INT_ENABLE;
|
||||
tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
|
||||
|
||||
if (request_locality(chip, 0) != 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
rc = tpm2_probe(chip);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
|
||||
rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
|
||||
priv->manufacturer_id = vendor;
|
||||
|
||||
rc = tpm_tis_read8(priv, TPM_RID(0), &rid);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
|
||||
dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
|
||||
(chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
|
||||
vendor >> 16, rid);
|
||||
|
||||
if (!(priv->flags & TPM_TIS_ITPM_POSSIBLE)) {
|
||||
probe = probe_itpm(chip);
|
||||
if (probe < 0) {
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (!!probe)
|
||||
priv->flags |= TPM_TIS_ITPM_POSSIBLE;
|
||||
}
|
||||
|
||||
/* Figure out the capabilities */
|
||||
rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
|
||||
if (rc < 0)
|
||||
goto out_err;
|
||||
|
||||
dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
|
||||
intfcaps);
|
||||
if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
|
||||
dev_dbg(dev, "\tBurst Count Static\n");
|
||||
if (intfcaps & TPM_INTF_CMD_READY_INT)
|
||||
dev_dbg(dev, "\tCommand Ready Int Support\n");
|
||||
if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
|
||||
dev_dbg(dev, "\tInterrupt Edge Falling\n");
|
||||
if (intfcaps & TPM_INTF_INT_EDGE_RISING)
|
||||
dev_dbg(dev, "\tInterrupt Edge Rising\n");
|
||||
if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
|
||||
dev_dbg(dev, "\tInterrupt Level Low\n");
|
||||
if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
|
||||
dev_dbg(dev, "\tInterrupt Level High\n");
|
||||
if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
|
||||
dev_dbg(dev, "\tLocality Change Int Support\n");
|
||||
if (intfcaps & TPM_INTF_STS_VALID_INT)
|
||||
dev_dbg(dev, "\tSts Valid Int Support\n");
|
||||
if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
|
||||
dev_dbg(dev, "\tData Avail Int Support\n");
|
||||
|
||||
/* Very early on issue a command to the TPM in polling mode to make
|
||||
* sure it works. May as well use that command to set the proper
|
||||
* timeouts for the driver.
|
||||
*/
|
||||
if (tpm_get_timeouts(chip)) {
|
||||
dev_err(dev, "Could not get TPM timeouts and durations\n");
|
||||
rc = -ENODEV;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* INTERRUPT Setup */
|
||||
init_waitqueue_head(&priv->read_queue);
|
||||
init_waitqueue_head(&priv->int_queue);
|
||||
if (irq != -1) {
|
||||
if (irq) {
|
||||
tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
|
||||
irq);
|
||||
if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
|
||||
dev_err(&chip->dev, FW_BUG
|
||||
"TPM interrupt not working, polling instead\n");
|
||||
} else {
|
||||
tpm_tis_probe_irq(chip, intmask);
|
||||
}
|
||||
}
|
||||
|
||||
return tpm_chip_register(chip);
|
||||
out_err:
|
||||
tpm_tis_remove(chip);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_tis_core_init);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
|
||||
{
|
||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||
u32 intmask;
|
||||
int rc;
|
||||
|
||||
/* reenable interrupts that device may have lost or
|
||||
* BIOS/firmware may have disabled
|
||||
*/
|
||||
rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq);
|
||||
if (rc < 0)
|
||||
return;
|
||||
|
||||
rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
|
||||
if (rc < 0)
|
||||
return;
|
||||
|
||||
intmask |= TPM_INTF_CMD_READY_INT
|
||||
| TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
|
||||
| TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
|
||||
|
||||
tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
|
||||
}
|
||||
|
||||
int tpm_tis_resume(struct device *dev)
|
||||
{
|
||||
struct tpm_chip *chip = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_IRQ)
|
||||
tpm_tis_reenable_interrupts(chip);
|
||||
|
||||
ret = tpm_pm_resume(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* TPM 1.2 requires self-test on resume. This function actually returns
|
||||
* an error code but for unknown reason it isn't handled.
|
||||
*/
|
||||
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
|
||||
tpm_do_selftest(chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_tis_resume);
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
|
||||
MODULE_DESCRIPTION("TPM Driver");
|
||||
MODULE_VERSION("2.0");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005, 2006 IBM Corporation
|
||||
* Copyright (C) 2014, 2015 Intel Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Leendert van Doorn <leendert@watson.ibm.com>
|
||||
* Kylene Hall <kjhall@us.ibm.com>
|
||||
*
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||
* Specifications at www.trustedcomputinggroup.org
|
||||
*
|
||||
* This device driver implements the TPM interface as defined in
|
||||
* the TCG TPM Interface Spec version 1.2, revision 1.0.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*/
|
||||
|
||||
#ifndef __TPM_TIS_CORE_H__
|
||||
#define __TPM_TIS_CORE_H__
|
||||
|
||||
#include "tpm.h"
|
||||
|
||||
enum tis_access {
|
||||
TPM_ACCESS_VALID = 0x80,
|
||||
TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
|
||||
TPM_ACCESS_REQUEST_PENDING = 0x04,
|
||||
TPM_ACCESS_REQUEST_USE = 0x02,
|
||||
};
|
||||
|
||||
enum tis_status {
|
||||
TPM_STS_VALID = 0x80,
|
||||
TPM_STS_COMMAND_READY = 0x40,
|
||||
TPM_STS_GO = 0x20,
|
||||
TPM_STS_DATA_AVAIL = 0x10,
|
||||
TPM_STS_DATA_EXPECT = 0x08,
|
||||
};
|
||||
|
||||
enum tis_int_flags {
|
||||
TPM_GLOBAL_INT_ENABLE = 0x80000000,
|
||||
TPM_INTF_BURST_COUNT_STATIC = 0x100,
|
||||
TPM_INTF_CMD_READY_INT = 0x080,
|
||||
TPM_INTF_INT_EDGE_FALLING = 0x040,
|
||||
TPM_INTF_INT_EDGE_RISING = 0x020,
|
||||
TPM_INTF_INT_LEVEL_LOW = 0x010,
|
||||
TPM_INTF_INT_LEVEL_HIGH = 0x008,
|
||||
TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
|
||||
TPM_INTF_STS_VALID_INT = 0x002,
|
||||
TPM_INTF_DATA_AVAIL_INT = 0x001,
|
||||
};
|
||||
|
||||
enum tis_defaults {
|
||||
TIS_MEM_LEN = 0x5000,
|
||||
TIS_SHORT_TIMEOUT = 750, /* ms */
|
||||
TIS_LONG_TIMEOUT = 2000, /* 2 sec */
|
||||
};
|
||||
|
||||
/* Some timeout values are needed before it is known whether the chip is
|
||||
* TPM 1.0 or TPM 2.0.
|
||||
*/
|
||||
#define TIS_TIMEOUT_A_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A)
|
||||
#define TIS_TIMEOUT_B_MAX max(TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B)
|
||||
#define TIS_TIMEOUT_C_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C)
|
||||
#define TIS_TIMEOUT_D_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D)
|
||||
|
||||
#define TPM_ACCESS(l) (0x0000 | ((l) << 12))
|
||||
#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12))
|
||||
#define TPM_INT_VECTOR(l) (0x000C | ((l) << 12))
|
||||
#define TPM_INT_STATUS(l) (0x0010 | ((l) << 12))
|
||||
#define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12))
|
||||
#define TPM_STS(l) (0x0018 | ((l) << 12))
|
||||
#define TPM_STS3(l) (0x001b | ((l) << 12))
|
||||
#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12))
|
||||
|
||||
#define TPM_DID_VID(l) (0x0F00 | ((l) << 12))
|
||||
#define TPM_RID(l) (0x0F04 | ((l) << 12))
|
||||
|
||||
enum tpm_tis_flags {
|
||||
TPM_TIS_ITPM_POSSIBLE = BIT(0),
|
||||
};
|
||||
|
||||
struct tpm_tis_data {
|
||||
u16 manufacturer_id;
|
||||
int locality;
|
||||
int irq;
|
||||
bool irq_tested;
|
||||
unsigned int flags;
|
||||
wait_queue_head_t int_queue;
|
||||
wait_queue_head_t read_queue;
|
||||
const struct tpm_tis_phy_ops *phy_ops;
|
||||
};
|
||||
|
||||
struct tpm_tis_phy_ops {
|
||||
int (*read_bytes)(struct tpm_tis_data *data, u32 addr, u16 len,
|
||||
u8 *result);
|
||||
int (*write_bytes)(struct tpm_tis_data *data, u32 addr, u16 len,
|
||||
const u8 *value);
|
||||
int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result);
|
||||
int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result);
|
||||
int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src);
|
||||
};
|
||||
|
||||
static inline int tpm_tis_read_bytes(struct tpm_tis_data *data, u32 addr,
|
||||
u16 len, u8 *result)
|
||||
{
|
||||
return data->phy_ops->read_bytes(data, addr, len, result);
|
||||
}
|
||||
|
||||
static inline int tpm_tis_read8(struct tpm_tis_data *data, u32 addr, u8 *result)
|
||||
{
|
||||
return data->phy_ops->read_bytes(data, addr, 1, result);
|
||||
}
|
||||
|
||||
static inline int tpm_tis_read16(struct tpm_tis_data *data, u32 addr,
|
||||
u16 *result)
|
||||
{
|
||||
return data->phy_ops->read16(data, addr, result);
|
||||
}
|
||||
|
||||
static inline int tpm_tis_read32(struct tpm_tis_data *data, u32 addr,
|
||||
u32 *result)
|
||||
{
|
||||
return data->phy_ops->read32(data, addr, result);
|
||||
}
|
||||
|
||||
static inline int tpm_tis_write_bytes(struct tpm_tis_data *data, u32 addr,
|
||||
u16 len, const u8 *value)
|
||||
{
|
||||
return data->phy_ops->write_bytes(data, addr, len, value);
|
||||
}
|
||||
|
||||
static inline int tpm_tis_write8(struct tpm_tis_data *data, u32 addr, u8 value)
|
||||
{
|
||||
return data->phy_ops->write_bytes(data, addr, 1, &value);
|
||||
}
|
||||
|
||||
static inline int tpm_tis_write32(struct tpm_tis_data *data, u32 addr,
|
||||
u32 value)
|
||||
{
|
||||
return data->phy_ops->write32(data, addr, value);
|
||||
}
|
||||
|
||||
void tpm_tis_remove(struct tpm_chip *chip);
|
||||
int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
|
||||
const struct tpm_tis_phy_ops *phy_ops,
|
||||
acpi_handle acpi_dev_handle);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int tpm_tis_resume(struct device *dev);
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,262 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Infineon Technologies AG
|
||||
* Copyright (C) 2016 STMicroelectronics SAS
|
||||
*
|
||||
* Authors:
|
||||
* Peter Huewe <peter.huewe@infineon.com>
|
||||
* Christophe Ricard <christophe-h.ricard@st.com>
|
||||
*
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||
* Specifications at www.trustedcomputinggroup.org
|
||||
*
|
||||
* This device driver implements the TPM interface as defined in
|
||||
* the TCG TPM Interface Spec version 1.3, revision 27 via _raw/native
|
||||
* SPI access_.
|
||||
*
|
||||
* It is based on the original tpm_tis device driver from Leendert van
|
||||
* Dorn and Kyleen Hall and Jarko Sakkinnen.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/tpm.h>
|
||||
#include "tpm.h"
|
||||
#include "tpm_tis_core.h"
|
||||
|
||||
#define MAX_SPI_FRAMESIZE 64
|
||||
#define mem_clear(data, size) memset((data), 0, (size))
|
||||
|
||||
struct tpm_tis_spi_phy {
|
||||
struct tpm_tis_data priv;
|
||||
struct spi_device *spi_device;
|
||||
u8 *iobuf;
|
||||
};
|
||||
|
||||
static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data)
|
||||
{
|
||||
return container_of(data, struct tpm_tis_spi_phy, priv);
|
||||
}
|
||||
|
||||
static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
|
||||
u8 *in, const u8 *out)
|
||||
{
|
||||
struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
|
||||
int ret = 0;
|
||||
int i;
|
||||
struct spi_message m;
|
||||
struct spi_transfer spi_xfer;
|
||||
u8 transfer_len;
|
||||
|
||||
spi_bus_lock(phy->spi_device->master);
|
||||
|
||||
while (len) {
|
||||
transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
|
||||
|
||||
phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
|
||||
phy->iobuf[1] = 0xd4;
|
||||
phy->iobuf[2] = addr >> 8;
|
||||
phy->iobuf[3] = addr;
|
||||
|
||||
mem_clear(&spi_xfer, sizeof(spi_xfer));
|
||||
spi_xfer.tx_buf = phy->iobuf;
|
||||
spi_xfer.rx_buf = phy->iobuf;
|
||||
spi_xfer.len = 4;
|
||||
spi_xfer.cs_change = 1;
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&spi_xfer, &m);
|
||||
ret = spi_sync_locked(phy->spi_device, &m);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
if ((phy->iobuf[3] & 0x01) == 0) {
|
||||
// handle SPI wait states
|
||||
phy->iobuf[0] = 0;
|
||||
|
||||
for (i = 0; i < TPM_RETRY; i++) {
|
||||
spi_xfer.len = 1;
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&spi_xfer, &m);
|
||||
ret = spi_sync_locked(phy->spi_device, &m);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
if (phy->iobuf[0] & 0x01)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == TPM_RETRY) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
spi_xfer.cs_change = 0;
|
||||
spi_xfer.len = transfer_len;
|
||||
spi_xfer.delay_usecs = 5;
|
||||
|
||||
if (in) {
|
||||
spi_xfer.tx_buf = NULL;
|
||||
} else if (out) {
|
||||
spi_xfer.rx_buf = NULL;
|
||||
memcpy(phy->iobuf, out, transfer_len);
|
||||
out += transfer_len;
|
||||
}
|
||||
|
||||
spi_message_init(&m);
|
||||
spi_message_add_tail(&spi_xfer, &m);
|
||||
ret = spi_sync_locked(phy->spi_device, &m);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
if (in) {
|
||||
memcpy(in, phy->iobuf, transfer_len);
|
||||
in += transfer_len;
|
||||
}
|
||||
|
||||
len -= transfer_len;
|
||||
}
|
||||
|
||||
exit:
|
||||
spi_bus_unlock(phy->spi_device->master);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
|
||||
u16 len, u8 *result)
|
||||
{
|
||||
return tpm_tis_spi_transfer(data, addr, len, result, NULL);
|
||||
}
|
||||
|
||||
static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr,
|
||||
u16 len, const u8 *value)
|
||||
{
|
||||
return tpm_tis_spi_transfer(data, addr, len, NULL, value);
|
||||
}
|
||||
|
||||
static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = data->phy_ops->read_bytes(data, addr, sizeof(u16), (u8 *)result);
|
||||
if (!rc)
|
||||
*result = le16_to_cpu(*result);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = data->phy_ops->read_bytes(data, addr, sizeof(u32), (u8 *)result);
|
||||
if (!rc)
|
||||
*result = le32_to_cpu(*result);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value)
|
||||
{
|
||||
value = cpu_to_le32(value);
|
||||
return data->phy_ops->write_bytes(data, addr, sizeof(u32),
|
||||
(u8 *)&value);
|
||||
}
|
||||
|
||||
static const struct tpm_tis_phy_ops tpm_spi_phy_ops = {
|
||||
.read_bytes = tpm_tis_spi_read_bytes,
|
||||
.write_bytes = tpm_tis_spi_write_bytes,
|
||||
.read16 = tpm_tis_spi_read16,
|
||||
.read32 = tpm_tis_spi_read32,
|
||||
.write32 = tpm_tis_spi_write32,
|
||||
};
|
||||
|
||||
static int tpm_tis_spi_probe(struct spi_device *dev)
|
||||
{
|
||||
struct tpm_tis_spi_phy *phy;
|
||||
int irq;
|
||||
|
||||
phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_spi_phy),
|
||||
GFP_KERNEL);
|
||||
if (!phy)
|
||||
return -ENOMEM;
|
||||
|
||||
phy->spi_device = dev;
|
||||
|
||||
phy->iobuf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
|
||||
if (!phy->iobuf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* If the SPI device has an IRQ then use that */
|
||||
if (dev->irq > 0)
|
||||
irq = dev->irq;
|
||||
else
|
||||
irq = -1;
|
||||
|
||||
return tpm_tis_core_init(&dev->dev, &phy->priv, irq, &tpm_spi_phy_ops,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
|
||||
|
||||
static int tpm_tis_spi_remove(struct spi_device *dev)
|
||||
{
|
||||
struct tpm_chip *chip = spi_get_drvdata(dev);
|
||||
|
||||
tpm_chip_unregister(chip);
|
||||
tpm_tis_remove(chip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id tpm_tis_spi_id[] = {
|
||||
{"tpm_tis_spi", 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, tpm_tis_spi_id);
|
||||
|
||||
static const struct of_device_id of_tis_spi_match[] = {
|
||||
{ .compatible = "st,st33htpm-spi", },
|
||||
{ .compatible = "infineon,slb9670", },
|
||||
{ .compatible = "tcg,tpm_tis-spi", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_tis_spi_match);
|
||||
|
||||
static const struct acpi_device_id acpi_tis_spi_match[] = {
|
||||
{"SMO0768", 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, acpi_tis_spi_match);
|
||||
|
||||
static struct spi_driver tpm_tis_spi_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "tpm_tis_spi",
|
||||
.pm = &tpm_tis_pm,
|
||||
.of_match_table = of_match_ptr(of_tis_spi_match),
|
||||
.acpi_match_table = ACPI_PTR(acpi_tis_spi_match),
|
||||
},
|
||||
.probe = tpm_tis_spi_probe,
|
||||
.remove = tpm_tis_spi_remove,
|
||||
.id_table = tpm_tis_spi_id,
|
||||
};
|
||||
module_spi_driver(tpm_tis_spi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("TPM Driver for native SPI access");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,285 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: UTF-8 -*-
|
||||
import click
|
||||
import os
|
||||
import time
|
||||
from ragileconfig import GLOBALCONFIG, GLOBALINITPARAM, GLOBALINITCOMMAND, MAC_LED_RESET, STARTMODULE, i2ccheck_params
|
||||
from ragileutil import rgpciwr, os_system
|
||||
|
||||
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
|
||||
|
||||
class AliasedGroup(click.Group):
|
||||
def get_command(self, ctx, cmd_name):
|
||||
rv = click.Group.get_command(self, ctx, cmd_name)
|
||||
if rv is not None:
|
||||
return rv
|
||||
else:
|
||||
return None
|
||||
matches = [x for x in self.list_commands(ctx)
|
||||
if x.startswith(cmd_name)]
|
||||
if not matches:
|
||||
return None
|
||||
elif len(matches) == 1:
|
||||
return click.Group.get_command(self, ctx, matches[0])
|
||||
ctx.fail('Too many matches: %s' % ', '.join(sorted(matches)))
|
||||
|
||||
def log_os_system(cmd):
|
||||
u'''execute shell command'''
|
||||
status, output = os_system(cmd)
|
||||
if status:
|
||||
print(output)
|
||||
return status, output
|
||||
|
||||
def write_sysfs_value(reg_name, value):
|
||||
u'''write sysfs file'''
|
||||
mb_reg_file = "/sys/bus/i2c/devices/" + reg_name
|
||||
if (not os.path.isfile(mb_reg_file)):
|
||||
print(mb_reg_file, 'not found !')
|
||||
return False
|
||||
try:
|
||||
with open(mb_reg_file, 'w') as fd:
|
||||
fd.write(value)
|
||||
except Exception as error:
|
||||
return False
|
||||
return True
|
||||
|
||||
def check_driver():
|
||||
u'''whether there is driver start with rg'''
|
||||
status, output = log_os_system("lsmod | grep rg | wc -l")
|
||||
#System execution error
|
||||
if status:
|
||||
return False
|
||||
if output.isdigit() and int(output) > 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_pid(name):
|
||||
ret = []
|
||||
for dirname in os.listdir('/proc'):
|
||||
if dirname == 'curproc':
|
||||
continue
|
||||
try:
|
||||
with open('/proc/{}/cmdline'.format(dirname), mode='r') as fd:
|
||||
content = fd.read()
|
||||
except Exception:
|
||||
continue
|
||||
if name in content:
|
||||
ret.append(dirname)
|
||||
return ret
|
||||
|
||||
def start_avs_ctrl():
|
||||
if STARTMODULE.get("avscontrol", 0) == 1:
|
||||
cmd = "nohup avscontrol.py start >/dev/null 2>&1 &"
|
||||
rets = get_pid("avscontrol.py")
|
||||
if len(rets) == 0:
|
||||
os.system(cmd)
|
||||
|
||||
def stop_avs_ctrl():
|
||||
if STARTMODULE.get('avscontrol', 0) == 1:
|
||||
rets = get_pid("avscontrol.py") #
|
||||
for ret in rets:
|
||||
cmd = "kill "+ ret
|
||||
os.system(cmd)
|
||||
|
||||
def start_fan_ctrl():
|
||||
if STARTMODULE.get('fancontrol', 0) == 1:
|
||||
cmd = "nohup fancontrol.py start >/dev/null 2>&1 &"
|
||||
rets = get_pid("fancontrol.py")
|
||||
if len(rets) == 0:
|
||||
os.system(cmd)
|
||||
|
||||
def stop_fan_ctrl():
|
||||
u'''disable fan timer service'''
|
||||
if STARTMODULE.get('fancontrol', 0) == 1:
|
||||
rets = get_pid("fancontrol.py") #
|
||||
for ret in rets:
|
||||
cmd = "kill "+ ret
|
||||
os.system(cmd)
|
||||
|
||||
def rm_dev(bus, loc):
|
||||
cmd = "echo 0x%02x > /sys/bus/i2c/devices/i2c-%d/delete_device" % (loc, bus)
|
||||
devpath = "/sys/bus/i2c/devices/%d-%04x"%(bus, loc)
|
||||
if os.path.exists(devpath):
|
||||
log_os_system(cmd)
|
||||
|
||||
def add_dev(name, bus, loc):
|
||||
if name == "lm75":
|
||||
time.sleep(0.1)
|
||||
pdevpath = "/sys/bus/i2c/devices/i2c-%d/" % (bus)
|
||||
for i in range(1, 100):#wait for mother-bus generation, maximum wait time is 10s
|
||||
if os.path.exists(pdevpath) == True:
|
||||
break
|
||||
time.sleep(0.1)
|
||||
if i % 10 == 0:
|
||||
click.echo("%%DEVICE_I2C-INIT: %s not found, wait 0.1 second ! i %d " % (pdevpath,i))
|
||||
|
||||
cmd = "echo %s 0x%02x > /sys/bus/i2c/devices/i2c-%d/new_device" % (name, loc, bus)
|
||||
devpath = "/sys/bus/i2c/devices/%d-%04x"%(bus, loc)
|
||||
if os.path.exists(devpath) == False:
|
||||
os.system(cmd)
|
||||
|
||||
def removedevs():
|
||||
devs = GLOBALCONFIG["DEVS"]
|
||||
for index in range(len(devs)-1, -1, -1 ):
|
||||
rm_dev(devs[index]["bus"] , devs[index]["loc"])
|
||||
|
||||
def adddevs():
|
||||
devs = GLOBALCONFIG["DEVS"]
|
||||
for dev in range(0, devs.__len__()):
|
||||
add_dev(devs[dev]["name"], devs[dev]["bus"] , devs[dev]["loc"])
|
||||
|
||||
def checksignaldriver(name):
|
||||
modisexistcmd = "lsmod | grep %s | wc -l" % name
|
||||
status, output = log_os_system(modisexistcmd)
|
||||
#System execution error
|
||||
if status:
|
||||
return False
|
||||
if output.isdigit() and int(output) > 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def adddriver(name, delay):
|
||||
cmd = "modprobe %s" % name
|
||||
if delay != 0:
|
||||
time.sleep(delay)
|
||||
if checksignaldriver(name) != True:
|
||||
log_os_system(cmd)
|
||||
|
||||
def removedriver(name, delay):
|
||||
realname = name.lstrip().split(" ")[0];
|
||||
cmd = "rmmod -f %s" % realname
|
||||
if checksignaldriver(realname):
|
||||
log_os_system(cmd)
|
||||
|
||||
def removedrivers():
|
||||
u'''remove all drivers'''
|
||||
if GLOBALCONFIG is None:
|
||||
click.echo("%%DEVICE_I2C-INIT: load global config failed.")
|
||||
return
|
||||
drivers = GLOBALCONFIG.get("DRIVERLISTS", None)
|
||||
if drivers is None:
|
||||
click.echo("%%DEVICE_I2C-INIT: load driver list failed.")
|
||||
return
|
||||
for index in range(len(drivers)-1, -1, -1 ):
|
||||
delay = 0
|
||||
name = ""
|
||||
if type(drivers[index]) == dict and "delay" in drivers[index]:
|
||||
name = drivers[index].get("name")
|
||||
delay = drivers[index]["delay"]
|
||||
else:
|
||||
name = drivers[index]
|
||||
removedriver(name, delay)
|
||||
|
||||
def adddrivers():
|
||||
u'''add drivers'''
|
||||
if GLOBALCONFIG is None:
|
||||
click.echo("%%DEVICE_I2C-INIT: load global config failed.")
|
||||
return
|
||||
drivers = GLOBALCONFIG.get("DRIVERLISTS", None)
|
||||
if drivers is None:
|
||||
click.echo("%%DEVICE_I2C-INIT: load driver list failed.")
|
||||
return
|
||||
for index in range(0 ,len(drivers)):
|
||||
delay = 0
|
||||
name = ""
|
||||
if type(drivers[index]) == dict and "delay" in drivers[index]:
|
||||
name = drivers[index].get("name")
|
||||
delay = drivers[index]["delay"]
|
||||
else:
|
||||
name = drivers[index]
|
||||
adddriver(name, delay)
|
||||
|
||||
def otherinit():
|
||||
for index in GLOBALINITPARAM:
|
||||
delay = index.get('delay',0)
|
||||
if delay !=0 :
|
||||
time.sleep(1)
|
||||
write_sysfs_value(index["loc"], index["value"])
|
||||
|
||||
for index in GLOBALINITCOMMAND:
|
||||
log_os_system(index)
|
||||
|
||||
def unload_driver():
|
||||
u'''remove devices and drivers'''
|
||||
stop_avs_ctrl() # disable avs-control
|
||||
stop_fan_ctrl() # disable fan-control service
|
||||
removedevs() # remove other devices
|
||||
removedrivers() # remove drivers
|
||||
|
||||
def reload_driver():
|
||||
u'''reload devices and drivers'''
|
||||
removedevs() # remove other devices
|
||||
removedrivers() # remove drivers
|
||||
time.sleep(1)
|
||||
adddrivers()
|
||||
adddevs()
|
||||
|
||||
|
||||
def i2c_check(bus,retrytime = 6):
|
||||
try:
|
||||
i2cpath = "/sys/bus/i2c/devices/" + bus
|
||||
while retrytime and not os.path.exists(i2cpath):
|
||||
click.echo("%%DEVICE_I2C-HA: i2c bus abnormal, last bus %s is not exist." % i2cpath)
|
||||
reload_driver()
|
||||
retrytime -= 1
|
||||
time.sleep(1)
|
||||
except Exception as e:
|
||||
click.echo("%%DEVICE_I2C-HA: %s" % str(e))
|
||||
return
|
||||
|
||||
def set_mac_leds(data):
|
||||
'''write pci register'''
|
||||
pcibus = MAC_LED_RESET.get("pcibus")
|
||||
slot = MAC_LED_RESET.get("slot")
|
||||
fn = MAC_LED_RESET.get("fn")
|
||||
bar = MAC_LED_RESET.get("bar")
|
||||
offset = MAC_LED_RESET.get("offset")
|
||||
val = MAC_LED_RESET.get(data, None)
|
||||
if val is None:
|
||||
click.echo("%%DEVICE_I2C-INIT: set_mac_leds wrong input")
|
||||
return
|
||||
rgpciwr(pcibus, slot, fn, bar, offset, val)
|
||||
|
||||
def load_driver():
|
||||
u'''load devices and drivers'''
|
||||
adddrivers()
|
||||
adddevs()
|
||||
if STARTMODULE.get("i2ccheck",0) == 1: #i2c HA
|
||||
busend = i2ccheck_params.get("busend")
|
||||
retrytime = i2ccheck_params.get("retrytime")
|
||||
i2c_check(busend,retrytime)
|
||||
start_fan_ctrl() # enable fan
|
||||
start_avs_ctrl() # avs voltage-adjustment
|
||||
otherinit(); # other initialization, QSFP initialization
|
||||
if STARTMODULE.get("macledreset", 0) == 1:
|
||||
set_mac_leds("reset")
|
||||
|
||||
@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS)
|
||||
def main():
|
||||
'''device operator'''
|
||||
pass
|
||||
|
||||
|
||||
@main.command()
|
||||
def start():
|
||||
'''load device '''
|
||||
if check_driver():
|
||||
unload_driver()
|
||||
load_driver()
|
||||
|
||||
@main.command()
|
||||
def stop():
|
||||
'''stop device '''
|
||||
unload_driver()
|
||||
|
||||
@main.command()
|
||||
def restart():
|
||||
'''restart device'''
|
||||
unload_driver()
|
||||
load_driver()
|
||||
|
||||
if __name__ == '__main__':
|
||||
u'''device_i2c operation'''
|
||||
main()
|
@ -1,497 +0,0 @@
|
||||
#!/usr/bin/env python3.9
|
||||
# -*- coding: UTF-8 -*-
|
||||
import click
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
import traceback
|
||||
from interface import Interface
|
||||
import logging.handlers
|
||||
from ragileutil import CompressedRotatingFileHandler
|
||||
|
||||
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
|
||||
|
||||
FILE_NAME = "/var/log/fancontrol.log"
|
||||
MAX_LOG_BYTES = 20*1024*1024
|
||||
BACKUP_COUNT = 9
|
||||
|
||||
logger = logging.getLogger("fancontrol")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
fanctrl_log = CompressedRotatingFileHandler(FILE_NAME, mode='a', maxBytes=MAX_LOG_BYTES, backupCount=BACKUP_COUNT, encoding=None, delay=0)
|
||||
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
|
||||
fanctrl_log.setFormatter(formatter)
|
||||
logger.addHandler(fanctrl_log)
|
||||
|
||||
DEBUG_FILE = "/etc/fancontrol_debug"
|
||||
FAN_CTRL_CFG_FILE = "/usr/local/bin/fan_ctrl_cfg.json"
|
||||
KEY_THERMAL = "Thermal"
|
||||
KEY_FAN = "Fans"
|
||||
KEY_PID = "PID"
|
||||
KEY_OPEN_LOOP = "OpenLoop"
|
||||
KEY_DEVICE = "Device"
|
||||
KEY_FAN_ERROR = "FanError"
|
||||
|
||||
KEY_FANERROR_PWM_MAX = "Fan_Pwmmax"
|
||||
|
||||
KEY_INLET_TEMP = "INLET_TEMP"
|
||||
KEY_OUTLET_TEMP = "OUTLET_TEMP"
|
||||
KEY_SWITCH_TEMP = "SWITCH_TEMP"
|
||||
KEY_TEMP = [KEY_INLET_TEMP, KEY_OUTLET_TEMP, KEY_SWITCH_TEMP]
|
||||
|
||||
KEY_PID_PWM_MAX = "Pwm_Max"
|
||||
KEY_PID_PWM_MIN = "Pwm_Min"
|
||||
KEY_PID_SETPOINT = "SetPoint"
|
||||
KEY_PID_P = "P"
|
||||
KEY_PID_I = "I"
|
||||
KEY_PID_D = "D"
|
||||
KEY_PID_TEMP_MIN = "Temp_Min"
|
||||
KEY_PID_TEMP_MAX = "Temp_Max"
|
||||
|
||||
KEY_OPENLOOP_A = "a"
|
||||
KEY_OPENLOOP_B = "b"
|
||||
KEY_OPENLOOP_C = "c"
|
||||
KEY_OPENLOOP_FIXUP = "fix_up"
|
||||
KEY_OPENLOOP_PWM_MAX = "pwmMax"
|
||||
KEY_OPENLOOP_PWM_MIN = "pwmMin"
|
||||
KEY_OPENLOOP_TEMP_MIN = "tempMin"
|
||||
|
||||
STATUS_HIGH_CRIT = 1
|
||||
STATUS_MISS_CRIT = 2
|
||||
STATUS_BAD_FAN = 4
|
||||
STATUS_LOW_FAN = 8
|
||||
STATUS_MISS_ERR = 16
|
||||
|
||||
class AliasedGroup(click.Group):
|
||||
def get_command(self, ctx, cmd_name):
|
||||
rv = click.Group.get_command(self, ctx, cmd_name)
|
||||
if rv is not None:
|
||||
return rv
|
||||
else:
|
||||
return None
|
||||
matches = [x for x in self.list_commands(ctx)
|
||||
if x.startswith(cmd_name)]
|
||||
if not matches:
|
||||
return None
|
||||
elif len(matches) == 1:
|
||||
return click.Group.get_command(self, ctx, matches[0])
|
||||
ctx.fail('Too many matches: %s' % ', '.join(sorted(matches)))
|
||||
|
||||
def fanctrl_debug_log(s):
|
||||
# s = s.decode('utf-8').encode('gb2312')
|
||||
if os.path.isfile(DEBUG_FILE):
|
||||
logger.debug(s)
|
||||
|
||||
class OpenLoop():
|
||||
def __init__(self):
|
||||
self.a = 0
|
||||
self.b = 0
|
||||
self.c = 0
|
||||
self.fix_up = 0
|
||||
self.pwmMax = 0
|
||||
self.pwmMin = 0
|
||||
self.temp = 0
|
||||
self.tempMin = 0
|
||||
|
||||
def calcPwm(self):
|
||||
if self.temp < self.tempMin:
|
||||
return self.pwmMin
|
||||
pwm = self.a * self.temp * self.temp + self.b * self.temp + self.c
|
||||
pwm = (pwm / 2.56)
|
||||
pwm = min(pwm, self.pwmMax)
|
||||
pwm = max(pwm, self.pwmMin)
|
||||
return pwm
|
||||
|
||||
|
||||
class FanPid():
|
||||
def __init__(self):
|
||||
self.pwmMin = 30
|
||||
self.pwmMax = 100
|
||||
self.SetPoint = 89
|
||||
self.D = 0.196
|
||||
self.I = 0.196
|
||||
self.P = 1.176
|
||||
self.tempMin = 28.0
|
||||
self.tempMax = 45.0
|
||||
self.pwms = [30, 30]
|
||||
self.temps = [-1, -1, -1]
|
||||
self.last_temp = -1
|
||||
self.sensor = KEY_SWITCH_TEMP
|
||||
|
||||
def calcPwm(self):
|
||||
temp_delta = self.temps[2] - self.last_temp
|
||||
temp_sp_delta = self.temps[2] - self.SetPoint
|
||||
temp_last_delta = ((self.temps[2] - self.temps[1]) - (self.temps[1] - self.temps[0]))
|
||||
|
||||
delta_pwm = self.P * temp_delta + self.I * temp_sp_delta + self.D * temp_last_delta
|
||||
|
||||
self.temps[0] = self.temps[1]
|
||||
self.temps[1] = self.temps[2]
|
||||
self.last_temp = self.temps[2]
|
||||
|
||||
self.pwms[0] = self.pwms[1]
|
||||
self.pwms[1] = self.pwms[0] + delta_pwm
|
||||
self.pwms[1] = max(self.pwms[1], self.pwmMin)
|
||||
self.pwms[1] = min(self.pwms[1], self.pwmMax)
|
||||
|
||||
return self.pwms[1]
|
||||
|
||||
class FanControl():
|
||||
|
||||
def __init__(self):
|
||||
self.status = 0
|
||||
self.fan_status = 0
|
||||
self.error_time = 0
|
||||
self.low_time = 0
|
||||
self.fan_pwm = 40
|
||||
self.fanerr_pwmmax = 0
|
||||
self.interface = Interface()
|
||||
self.temps = {}
|
||||
self.tempsMax = {}
|
||||
self.tempsMin = {}
|
||||
self.tempStatus = {}
|
||||
self.tempCritTime = {}
|
||||
self.tempMissTime = {}
|
||||
|
||||
self.fans = {}
|
||||
self.fanStatus = {}
|
||||
self.fanErrTime = {}
|
||||
self.fanLowTime = {}
|
||||
|
||||
self.fanPid = None
|
||||
self.openloop = None
|
||||
|
||||
self.isBuildin = 0
|
||||
self.isLiquid = 0
|
||||
self.eeproms = {}
|
||||
self.airflow = ""
|
||||
self.pid_switch = 1
|
||||
self.openloop_switch = 1
|
||||
|
||||
def doGetAirFlow(self):
|
||||
if self.isLiquid == 1:
|
||||
return "Liquid"
|
||||
# PSU and Fan is buildin using Tlve2
|
||||
if self.isBuildin == 1:
|
||||
productName = self.interface.get_productname()
|
||||
if productName != "":
|
||||
tmp = productName.split("-")
|
||||
fanairflow = tmp[-1]
|
||||
if fanairflow == "R":
|
||||
return "exhaust"
|
||||
else:
|
||||
return "intake"
|
||||
elif self.isBuildin == 0:
|
||||
return self.interface.get_airflow()
|
||||
|
||||
return ""
|
||||
|
||||
def doFanCtrlInit(self):
|
||||
if os.path.isfile(FAN_CTRL_CFG_FILE):
|
||||
fh = open(FAN_CTRL_CFG_FILE)
|
||||
if not fh:
|
||||
logger.error("Config file %s doesn't exist" % FAN_CTRL_CFG_FILE)
|
||||
return False
|
||||
cfg_json = json.load(fh)
|
||||
if not cfg_json:
|
||||
logger.error('Load config file %s failed' % FAN_CTRL_CFG_FILE)
|
||||
fh.close()
|
||||
return False
|
||||
|
||||
cfg_keys = [KEY_THERMAL, KEY_FAN, KEY_PID, KEY_OPEN_LOOP, KEY_DEVICE, KEY_FAN_ERROR]
|
||||
for key in cfg_keys:
|
||||
if key not in cfg_json:
|
||||
logger.error('Key %s not present in cfg file' % key)
|
||||
return False
|
||||
thermal_json = cfg_json[KEY_THERMAL]
|
||||
fan_json = cfg_json[KEY_FAN]
|
||||
pid_json = cfg_json[KEY_PID]
|
||||
openloop_json = cfg_json[KEY_OPEN_LOOP]
|
||||
device_json = cfg_json[KEY_DEVICE]
|
||||
fan_error_json = cfg_json[KEY_FAN_ERROR]
|
||||
|
||||
#init fanerror
|
||||
self.fanerr_pwmmax = fan_error_json["Fan_Pwmmax"]
|
||||
|
||||
# Get Airflow
|
||||
self.isBuildin = device_json["Buildin"]
|
||||
self.isLiquid = device_json["Liquid"]
|
||||
self.airflow = self.doGetAirFlow()
|
||||
if self.airflow == "":
|
||||
logger.warning("Cannot get airflow from device!")
|
||||
self.pid_switch = device_json["PID"]
|
||||
self.openloop_switch = device_json["OpenLoop"]
|
||||
if self.pid_switch == 0 and self.openloop_switch == 0:
|
||||
logger.warning("No PID and OpenLoop found!")
|
||||
# Init openloop
|
||||
self.openloop = OpenLoop()
|
||||
self.openloop.a = openloop_json[KEY_OPENLOOP_A]
|
||||
self.openloop.b = openloop_json[KEY_OPENLOOP_B]
|
||||
self.openloop.c = openloop_json[KEY_OPENLOOP_C]
|
||||
self.openloop.fix_up = openloop_json[KEY_OPENLOOP_FIXUP]
|
||||
self.openloop.pwmMax = openloop_json[KEY_OPENLOOP_PWM_MAX]
|
||||
self.openloop.pwmMin = openloop_json[KEY_OPENLOOP_PWM_MIN]
|
||||
self.openloop.tempMin = openloop_json[KEY_OPENLOOP_TEMP_MIN]
|
||||
# Init PID
|
||||
self.fanPid = FanPid()
|
||||
self.fanPid.pwmMax = pid_json[KEY_PID_PWM_MAX]
|
||||
self.fanPid.pwmMin = pid_json[KEY_PID_PWM_MIN]
|
||||
self.fanPid.SetPoint = pid_json[KEY_PID_SETPOINT]
|
||||
self.fanPid.P = pid_json[KEY_PID_P]
|
||||
self.fanPid.I = pid_json[KEY_PID_I]
|
||||
self.fanPid.D = pid_json[KEY_PID_D]
|
||||
self.fanPid.tempMin = pid_json[KEY_PID_TEMP_MIN]
|
||||
self.fanPid.tempMax = pid_json[KEY_PID_TEMP_MAX]
|
||||
# Init thermal setting
|
||||
for key, item in list(thermal_json.items()):
|
||||
fanctrl_debug_log("%s %s " % (key,item))
|
||||
if key not in KEY_TEMP:
|
||||
logger.error('Key %s not present in cfg file' % key)
|
||||
return False
|
||||
self.temps[item] = -1.0
|
||||
self.tempsMax[item] = self.interface.get_thermal_temp_max(item)
|
||||
self.tempsMin[item] = self.interface.get_thermal_temp_min(item)
|
||||
self.tempStatus[item] = 0
|
||||
self.tempMissTime[item] = [0, 0]
|
||||
self.tempCritTime[item] = [0, 0]
|
||||
if key == self.fanPid.sensor:
|
||||
self.fanPid.sensor = item
|
||||
|
||||
# Init fans setting
|
||||
for key, item in list(fan_json.items()):
|
||||
self.fans[key] = item
|
||||
self.fanStatus[key] = 0
|
||||
self.fanErrTime[key] = [0, 0]
|
||||
self.fanLowTime[key] = [0, 0]
|
||||
fh.close()
|
||||
else:
|
||||
logger.error('%s is not a file' % FAN_CTRL_CFG_FILE)
|
||||
return False
|
||||
|
||||
fanctrl_debug_log("Device AirFlow: %s" % (self.airflow))
|
||||
self.updateThermal()
|
||||
self.fanPid.last_temp = self.temps[self.fanPid.sensor]
|
||||
for i in range(3):
|
||||
self.fanPid.temps[i] = self.temps[self.fanPid.sensor]
|
||||
return True
|
||||
|
||||
def setFanSpeed(self, speed):
|
||||
return self.interface.set_fan_speed_pwm(speed)
|
||||
|
||||
def updateThermal(self):
|
||||
for key in self.temps:
|
||||
self.temps[key] = self.interface.get_thermal_temp(key)
|
||||
fanctrl_debug_log("%s temps %d C" % (key, self.temps[key]))
|
||||
|
||||
if self.temps[KEY_INLET_TEMP] >= self.tempsMax[KEY_INLET_TEMP] or self.temps[KEY_INLET_TEMP] <= -99999:
|
||||
self.temps[KEY_INLET_TEMP] = self.tempsMax[KEY_INLET_TEMP]
|
||||
self.openloop.temp = self.temps[KEY_INLET_TEMP]
|
||||
self.fanPid.temps[2] = self.temps[KEY_INLET_TEMP]
|
||||
|
||||
def checkThermal(self):
|
||||
thermal_cnt = 0
|
||||
for key in self.temps:
|
||||
if self.temps[key] <= -9999:
|
||||
if self.tempStatus[key] & STATUS_MISS_CRIT != 0:
|
||||
self.tempMissTime[key][0] = time.time()
|
||||
else:
|
||||
self.tempMissTime[key][1] = time.time()
|
||||
self.tempStatus[key] = self.tempStatus[key] | STATUS_MISS_CRIT
|
||||
if self.tempMissTime[key][1] - self.tempMissTime[key][0] > 15:
|
||||
logger.warning("%s Read Invaild Temperautre %d " % (key, self.temps[key]))
|
||||
self.tempStatus[key] = self.tempStatus[key] | STATUS_MISS_ERR
|
||||
else:
|
||||
self.tempStatus[key] = self.tempStatus[key] & ~(STATUS_MISS_CRIT | STATUS_MISS_ERR)
|
||||
|
||||
if self.temps[key] >= self.tempsMax[key]:
|
||||
self.tempCritTime[key][0] = time.time()
|
||||
self.tempStatus[key] = self.tempStatus[key] | STATUS_HIGH_CRIT
|
||||
logger.warning("%s Temperautre %d >= High Threshold %d" % (key, self.temps[key], self.tempsMax[key]))
|
||||
elif self.tempStatus[key] & (STATUS_HIGH_CRIT) != 0:
|
||||
self.tempCritTime[key][1] = time.time()
|
||||
logger.warning("%s Temperautre %d Recovery" % (key, self.temps[key]))
|
||||
if self.tempCritTime[key][1] - self.tempCritTime[key][0] > 300:
|
||||
self.tempStatus[key] = self.tempStatus[key] & ~(STATUS_HIGH_CRIT)
|
||||
|
||||
if self.tempStatus[key] & ~(STATUS_MISS_CRIT) != 0:
|
||||
thermal_cnt = thermal_cnt + 1
|
||||
|
||||
self.status = thermal_cnt
|
||||
fanctrl_debug_log("Thermal error num %d" % self.status)
|
||||
|
||||
def checkFanSpeed(self):
|
||||
fan_error_cnt = 0
|
||||
for key, item in list(self.fans.items()):
|
||||
speed = self.interface.get_fan_speed_rpm(item)
|
||||
rpm_max = self.interface.get_fan_rpm_max()
|
||||
if self.fan_pwm == 100 and speed < rpm_max * 0.7:
|
||||
if self.fanStatus[key] & STATUS_BAD_FAN != 0:
|
||||
self.fanErrTime[key][0] = time.time()
|
||||
else:
|
||||
self.fanErrTime[key][1] = time.time()
|
||||
|
||||
self.fanStatus[key] = self.fanStatus[key] | STATUS_BAD_FAN
|
||||
if self.fanErrTime[key][1] - self.fanErrTime[key][0] >= 30:
|
||||
logger.warning("%s PWM is %d but Speed %d <= %d RPM" % (item, self.fan_pwm, speed, rpm_max * 0.7))
|
||||
else:
|
||||
self.fanStatus[key] = self.fanStatus[key] & ~(STATUS_BAD_FAN)
|
||||
|
||||
if speed < 1000:
|
||||
if self.fanStatus[key] & STATUS_LOW_FAN != 0:
|
||||
self.fanLowTime[key][0] = time.time()
|
||||
else:
|
||||
self.fanLowTime[key][1] = time.time()
|
||||
self.fanStatus[key] = self.fanStatus[key] | STATUS_LOW_FAN
|
||||
if self.fanLowTime[key][1] - self.fanLowTime[key][0] > 30:
|
||||
logger.warning("%s Speed %d <= %d RPM" % (item, speed, 1000))
|
||||
else:
|
||||
self.fanStatus[key] = self.fanStatus[key] & ~(STATUS_LOW_FAN)
|
||||
|
||||
fanctrl_debug_log("%s speed %d RPM" % (key, speed))
|
||||
|
||||
if self.fanStatus[key] != 0:
|
||||
fan_error_cnt = fan_error_cnt + 1
|
||||
self.fan_status = fan_error_cnt
|
||||
fanctrl_debug_log("Fan error num %d" % fan_error_cnt)
|
||||
|
||||
def doApplyPolicy(self):
|
||||
if self.isLiquid == 1:
|
||||
return
|
||||
|
||||
self.fan_pwm = 0
|
||||
if self.openloop_switch == 1:
|
||||
openloop_pwm = int(self.openloop.calcPwm())
|
||||
fanctrl_debug_log("OpenLoop pwm %d" % (openloop_pwm))
|
||||
self.fan_pwm = max(self.fan_pwm, openloop_pwm)
|
||||
|
||||
if self.pid_switch == 1:
|
||||
pid_pwm = int(self.fanPid.calcPwm())
|
||||
fanctrl_debug_log("PID pwm %d" % (pid_pwm))
|
||||
self.fan_pwm = max(self.fan_pwm, pid_pwm)
|
||||
|
||||
# Check fan presence
|
||||
if self.interface.get_fan_presence() == False:
|
||||
logger.warning("Fan presence check false, set fan pwm to 100")
|
||||
self.fan_pwm = self.fanerr_pwmmax
|
||||
if self.fan_status != 0 or self.status != 0:
|
||||
self.fan_pwm = self.fanerr_pwmmax
|
||||
fanctrl_debug_log("Fan Speed set to %d pwm" % self.fan_pwm)
|
||||
for i in range(3):
|
||||
ret = self.setFanSpeed(self.fan_pwm)
|
||||
if ret == False:
|
||||
logger.warning("Fan speed set %d pwm failed, retry %d times" % (self.fan_pwm, i + 1))
|
||||
continue
|
||||
break
|
||||
|
||||
def doBoardFanLedCtrl(self):
|
||||
if self.interface.get_fan_status() != False and self.interface.get_fan_presence() != False and self.fan_status == 0:
|
||||
fanctrl_debug_log("Fan status good setting LED to green")
|
||||
self.interface.set_fan_board_led("green")
|
||||
else:
|
||||
fanctrl_debug_log("Fan status error setting LED to red")
|
||||
self.interface.set_fan_board_led("red")
|
||||
|
||||
def doBoardPsuLedCtrl(self):
|
||||
if self.interface.get_psu_status() != False:
|
||||
fanctrl_debug_log("PSU status good setting LED to green")
|
||||
self.interface.set_psu_board_led("green")
|
||||
else:
|
||||
fanctrl_debug_log("PSU status error setting LED to red")
|
||||
self.interface.set_psu_board_led("red")
|
||||
|
||||
def doSysLedCtrl(self):
|
||||
self.interface.set_sysled("green")
|
||||
|
||||
def run(interval, fanCtrol):
|
||||
loop = 0
|
||||
# waitForDocker()
|
||||
fanCtrol.setFanSpeed(fanCtrol.fan_pwm) #init set fan speed to 50 pwm
|
||||
fanCtrol.doFanCtrlInit()
|
||||
if fanCtrol.airflow == "Liquid":
|
||||
logger.warning('Liquid device stopping fancontrol')
|
||||
return True
|
||||
while True:
|
||||
try:
|
||||
if loop % 5 == 0: # Fan speed control
|
||||
try:
|
||||
fanCtrol.updateThermal()
|
||||
except Exception as e:
|
||||
logger.error('Failed: Update Thermal, %s' % str(e))
|
||||
logger.error('%s' % traceback.format_exc())
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
try:
|
||||
fanCtrol.checkThermal()
|
||||
except Exception as e:
|
||||
logger.error('Failed: Check Thermal, %s' % str(e))
|
||||
logger.error('%s' % traceback.format_exc())
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
try:
|
||||
fanCtrol.checkFanSpeed()
|
||||
except Exception as e:
|
||||
logger.error('Failed: Check Fan Speed, %s' % str(e))
|
||||
logger.error('%s' % traceback.format_exc())
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
try:
|
||||
fanCtrol.doApplyPolicy()
|
||||
except Exception as e:
|
||||
logger.error('Failed: Apply Policy, %s' % str(e))
|
||||
logger.error('%s' % traceback.format_exc())
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
try:
|
||||
fanCtrol.doBoardFanLedCtrl()
|
||||
except Exception as e:
|
||||
logger.error('Failed: Led Control, %s' % str(e))
|
||||
logger.error('%s' % traceback.format_exc())
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
try:
|
||||
fanCtrol.doBoardPsuLedCtrl()
|
||||
except Exception as e:
|
||||
logger.error('Failed: Led Control, %s' % str(e))
|
||||
logger.error('%s' % traceback.format_exc())
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
try:
|
||||
fanCtrol.doSysLedCtrl()
|
||||
except Exception as e:
|
||||
logger.error('Failed: Led Control, %s' % str(e))
|
||||
logger.error('%s' % traceback.format_exc())
|
||||
time.sleep(3)
|
||||
continue
|
||||
|
||||
time.sleep(interval)
|
||||
loop += interval
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
logger.error(str(e))
|
||||
|
||||
@click.group(cls=AliasedGroup, context_settings=CONTEXT_SETTINGS)
|
||||
def main():
|
||||
'''device operator'''
|
||||
pass
|
||||
|
||||
@main.command()
|
||||
def start():
|
||||
'''start fan control'''
|
||||
logger.info("FANCTROL start")
|
||||
fanCtrol = FanControl()
|
||||
interval = 1
|
||||
run(interval, fanCtrol)
|
||||
|
||||
@main.command()
|
||||
def stop():
|
||||
'''stop fan control '''
|
||||
logger.info("FANCTROL stop")
|
||||
|
||||
# device_i2c operation
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -1,77 +0,0 @@
|
||||
from sonic_platform.chassis import Chassis
|
||||
|
||||
class Interface():
|
||||
def __init__(self):
|
||||
self.chassis = Chassis()
|
||||
self.fan_list = self.chassis._fan_list
|
||||
self.thermal_list = self.chassis._thermal_list
|
||||
self.psu_list = self.chassis._psu_list
|
||||
# Device
|
||||
def get_productname(self):
|
||||
return self.chassis.get_name()
|
||||
|
||||
def set_sysled(self, color):
|
||||
return self.thermal_list[0].set_sys_led(color)
|
||||
|
||||
# Thermal
|
||||
def get_thermal_temp_max(self, name):
|
||||
for thermal in self.thermal_list:
|
||||
if name == thermal.get_real_name():
|
||||
return thermal.get_high_threshold()
|
||||
|
||||
def get_thermal_temp_min(self, name):
|
||||
for thermal in self.thermal_list:
|
||||
if name == thermal.get_real_name():
|
||||
return thermal.get_low_threshold()
|
||||
|
||||
def get_thermal_temp(self, name):
|
||||
for thermal in self.thermal_list:
|
||||
if name == thermal.get_real_name():
|
||||
return thermal.get_temperature()
|
||||
# Fans
|
||||
def set_fan_speed_pwm(self, speed):
|
||||
return self.fan_list[0].set_speed_pwm(speed)
|
||||
|
||||
def get_fan_status(self):
|
||||
for fan in self.fan_list:
|
||||
if fan.get_status() == False:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_fan_presence(self):
|
||||
for fan in self.fan_list:
|
||||
if fan.get_presence() == False:
|
||||
return False
|
||||
return True
|
||||
|
||||
def set_fan_board_led(self, color):
|
||||
return self.fan_list[0].set_status_led(color)
|
||||
|
||||
def get_fan_speed_rpm(self, name):
|
||||
for fan in self.fan_list:
|
||||
if name == fan.get_name():
|
||||
return fan.get_speed_rpm()
|
||||
return 0
|
||||
|
||||
def get_fan_rpm_max(self):
|
||||
return self.fan_list[0].get_high_critical_threshold()
|
||||
|
||||
def get_airflow(self):
|
||||
tmp1 = self.fan_list[0].get_direction()
|
||||
tmp2 = self.fan_list[0].get_direction()
|
||||
for fan in self.fan_list:
|
||||
tmp1 = fan.get_direction()
|
||||
if tmp1 != tmp2:
|
||||
return "F2B"
|
||||
tmp2 = tmp1
|
||||
return tmp2
|
||||
# Psus
|
||||
def get_psu_status(self):
|
||||
for psu in self.psu_list:
|
||||
if psu.get_powergood_status == False:
|
||||
return False
|
||||
return True
|
||||
|
||||
def set_psu_board_led(self, color):
|
||||
return self.psu_list[0].set_status_led(color)
|
||||
|
@ -1,92 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
# * onboard sensors
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
from sonic_platform.redfish_api import Redfish_Api
|
||||
|
||||
def get_machine_info():
|
||||
if not os.path.isfile('/host/machine.conf'):
|
||||
return None
|
||||
machine_vars = {}
|
||||
with open('/host/machine.conf') as machine_file:
|
||||
for line in machine_file:
|
||||
tokens = line.split('=')
|
||||
if len(tokens) < 2:
|
||||
continue
|
||||
machine_vars[tokens[0]] = tokens[1].strip()
|
||||
return machine_vars
|
||||
|
||||
def get_platform_info(machine_info):
|
||||
if machine_info is not None:
|
||||
if 'onie_platform' in machine_info:
|
||||
return machine_info['onie_platform']
|
||||
elif 'aboot_platform' in machine_info:
|
||||
return machine_info['aboot_platform']
|
||||
return None
|
||||
|
||||
PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
|
||||
platform = None
|
||||
|
||||
def get_platform_name():
|
||||
global platform
|
||||
platform = get_platform_info(get_machine_info())
|
||||
return platform
|
||||
|
||||
val = get_platform_name()
|
||||
sys.path.append("/".join([PLATFORM_ROOT_PATH, platform]))
|
||||
|
||||
def print_console(str):
|
||||
print(str)
|
||||
|
||||
def print_platform():
|
||||
platform_info = get_platform_name()
|
||||
print_console(platform_info)
|
||||
print_console('Adapter: Ragile Platform Management Controller')
|
||||
print_console("")
|
||||
|
||||
def get_sensor():
|
||||
sensor = Redfish_Api().get_thresholdSensors()
|
||||
ctrl = sensor["Sensors"]
|
||||
list_sensor =[]
|
||||
for item in ctrl:
|
||||
name = item.get("@odata.id").split("/",9)[9]
|
||||
now = item.get("Reading")
|
||||
min = item.get("Thresholds").get("LowerFatal").get("Reading")
|
||||
max = item.get("Thresholds").get("UpperFatal").get("Reading")
|
||||
unit = item.get("ReadingUnits")
|
||||
if unit == "Amps":
|
||||
unit = "A"
|
||||
if min == (-1000):
|
||||
min = (min/1000)
|
||||
elif unit == "Volts":
|
||||
unit = "V"
|
||||
tmp = {}
|
||||
tmp["name"]= name
|
||||
tmp["now"] = ("%.3f" % now)
|
||||
tmp["min"] = ("%.3f" % min)
|
||||
tmp["max"] = ("%.3f" % max)
|
||||
tmp["unit"] = unit
|
||||
list_sensor.append(tmp)
|
||||
return list_sensor
|
||||
|
||||
def print_boarddcdc():
|
||||
val_ret = get_sensor()
|
||||
print_info_str = ""
|
||||
toptile = "Onboard Sensors:"
|
||||
errformat = " {id:<26} : {errmsg}"
|
||||
formatstr = " {name:<26} : {now:<6} {unit:<1} (Min = {min:<6} {unit:<1} , Max = {max:<6} {unit:<1} )"
|
||||
|
||||
if len(val_ret) != 0:
|
||||
print_info_str += toptile + '\n'
|
||||
for item in val_ret:
|
||||
realformat = formatstr if item.get('errcode', 0) == 0 else errformat
|
||||
print_info_str += realformat.format(**item) + '\n'
|
||||
print_console(print_info_str)
|
||||
|
||||
def getsensors():
|
||||
print_platform()
|
||||
print_boarddcdc()
|
||||
|
||||
if __name__ == "__main__":
|
||||
getsensors()
|
File diff suppressed because it is too large
Load Diff
@ -1,228 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: UTF-8 -*-
|
||||
# -------------------------------------------------------------------------------
|
||||
# Name: ragileconfig.py
|
||||
# Purpose: block the difference between various product/onie version for other module
|
||||
#
|
||||
# Author: rd
|
||||
#
|
||||
# Created: 02/07/2018
|
||||
# Copyright: (c) rd 2018
|
||||
# -------------------------------------------------------------------------------
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
from rgutil.baseutil import get_machine_info
|
||||
from rgutil.baseutil import get_platform_info
|
||||
|
||||
__all__ = [
|
||||
"getdeviceplatform",
|
||||
"get_rjconfig_info",
|
||||
"MONITOR_CONST",
|
||||
"MAILBOX_DIR",
|
||||
"DEVICE",
|
||||
"GLOBALCONFIG",
|
||||
"GLOBALINITPARAM",
|
||||
"GLOBALINITCOMMAND",
|
||||
"MAC_LED_RESET",
|
||||
"STARTMODULE",
|
||||
"fanloc",
|
||||
"RAGILE_CARDID",
|
||||
"RAGILE_PRODUCTNAME",
|
||||
"RAGILE_PART_NUMBER",
|
||||
"RAGILE_LABEL_REVISION",
|
||||
"RAGILE_MAC_SIZE",
|
||||
"RAGILE_MANUF_NAME",
|
||||
"RAGILE_MANUF_COUNTRY",
|
||||
"RAGILE_VENDOR_NAME",
|
||||
"RAGILE_DIAG_VERSION",
|
||||
"RAGILE_SERVICE_TAG",
|
||||
"E2_PROTECT",
|
||||
"E2_LOC",
|
||||
"FAN_PROTECT",
|
||||
"FANS_DEF",
|
||||
"MONITOR_FANS_LED",
|
||||
"MONITOR_SYS_FAN_LED",
|
||||
"MONITOR_SYS_PSU_LED",
|
||||
"MONITOR_FAN_STATUS",
|
||||
"MONITOR_PSU_STATUS",
|
||||
"MONITOR_DEV_STATUS",
|
||||
"MONITOR_DEV_STATUS_DECODE",
|
||||
"DEV_LEDS",
|
||||
"MAC_AVS_PARAM",
|
||||
"MAC_DEFAULT_PARAM",
|
||||
"FRULISTS",
|
||||
"rg_eeprom",
|
||||
"i2ccheck_params",
|
||||
"FANCTROLDEBUG",
|
||||
"DEVMONITORDEBUG",
|
||||
]
|
||||
|
||||
|
||||
def getdeviceplatform():
|
||||
x = get_platform_info(get_machine_info())
|
||||
if x != None:
|
||||
filepath = "/usr/share/sonic/device/" + x
|
||||
return filepath
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
platform = get_platform_info(get_machine_info())
|
||||
platformpath = getdeviceplatform()
|
||||
MAILBOX_DIR = "/sys/bus/i2c/devices/"
|
||||
grtd_productfile = (platform + "_config").replace("-", "_")
|
||||
common_productfile = "ragilecommon"
|
||||
configfile_pre = "/usr/local/bin/"
|
||||
|
||||
sys.path.append(platformpath)
|
||||
sys.path.append(configfile_pre)
|
||||
|
||||
|
||||
def get_rjconfig_info(attr_key):
|
||||
rjconf_filename = platformpath + "/plugins" + "/rj.conf"
|
||||
if not os.path.isfile(rjconf_filename):
|
||||
return None
|
||||
with open(rjconf_filename) as rjconf_file:
|
||||
for line in rjconf_file:
|
||||
tokens = line.split("=")
|
||||
if len(tokens) < 2:
|
||||
continue
|
||||
if tokens[0] == attr_key:
|
||||
return tokens[1].strip()
|
||||
return None
|
||||
|
||||
|
||||
#####BMC-Password###
|
||||
OPENBMC_PASSWORD = get_rjconfig_info("OPENBMC_PASSWORD")
|
||||
OPENBMC_PASSWORD = OPENBMC_PASSWORD if (OPENBMC_PASSWORD != None) else "0penBmc"
|
||||
|
||||
############################################################################################
|
||||
## if there is no specific file, use common file
|
||||
module_product = None
|
||||
if os.path.exists(configfile_pre + grtd_productfile + ".py"):
|
||||
module_product = __import__(grtd_productfile, globals(), locals(), [], 0)
|
||||
elif os.path.exists(configfile_pre + common_productfile + ".py"):
|
||||
module_product = __import__(common_productfile, globals(), locals(), [], 0)
|
||||
else:
|
||||
logging.info("No Configuration existed, quit")
|
||||
exit(-1)
|
||||
############################################################################################
|
||||
|
||||
DEVICE = module_product.DEVICE
|
||||
|
||||
##########Driver loading needs parameters
|
||||
# get different product configuration
|
||||
RAGILE_GLOBALCONFIG = {
|
||||
"DRIVERLISTS": module_product.DRIVERLISTS,
|
||||
"QSFP": {
|
||||
"startbus": module_product.PCA9548START,
|
||||
"endbus": module_product.PCA9548BUSEND,
|
||||
},
|
||||
"DEVS": DEVICE,
|
||||
}
|
||||
GLOBALCONFIG = RAGILE_GLOBALCONFIG
|
||||
GLOBALINITPARAM = module_product.INIT_PARAM
|
||||
GLOBALINITCOMMAND = module_product.INIT_COMMAND
|
||||
|
||||
fancontrol_loc = module_product.fancontrol_loc
|
||||
fancontrol_config_loc = module_product.fancontrol_config_loc
|
||||
MAC_LED_RESET = module_product.MAC_LED_RESET
|
||||
###########Stat-up module parameters
|
||||
STARTMODULE = module_product.STARTMODULE
|
||||
FIRMWARE_TOOLS = module_product.FIRMWARE_TOOLS
|
||||
|
||||
|
||||
##########Manufacturing-Test need parameters
|
||||
FACTESTMODULE = module_product.FACTESTMODULE
|
||||
TESTCASE = module_product.TESTCASE
|
||||
menuList = module_product.menuList
|
||||
alltest = module_product.alltest
|
||||
diagtestall = module_product.diagtestall
|
||||
looptest = module_product.looptest
|
||||
fanloc = module_product.fanloc
|
||||
fanlevel = module_product.fanlevel # fan adjustment level
|
||||
TEMPIDCHANGE = module_product.TEMPIDCHANGE
|
||||
CPLDVERSIONS = module_product.CPLDVERSIONS
|
||||
RAGILE_CARDID = module_product.RAGILE_CARDID
|
||||
RAGILE_PRODUCTNAME = module_product.RAGILE_PRODUCTNAME
|
||||
|
||||
RAGILE_PART_NUMBER = module_product.RAGILE_PART_NUMBER
|
||||
RAGILE_LABEL_REVISION = module_product.RAGILE_LABEL_REVISION
|
||||
RAGILE_ONIE_VERSION = module_product.RAGILE_ONIE_VERSION
|
||||
RAGILE_MAC_SIZE = module_product.RAGILE_MAC_SIZE
|
||||
RAGILE_MANUF_NAME = module_product.RAGILE_MANUF_NAME
|
||||
RAGILE_MANUF_COUNTRY = module_product.RAGILE_MANUF_COUNTRY
|
||||
RAGILE_VENDOR_NAME = module_product.RAGILE_VENDOR_NAME
|
||||
RAGILE_DIAG_VERSION = module_product.RAGILE_DIAG_VERSION
|
||||
RAGILE_SERVICE_TAG = module_product.RAGILE_SERVICE_TAG
|
||||
|
||||
E2_PROTECT = module_product.E2_PROTECT
|
||||
E2_LOC = module_product.E2_LOC
|
||||
FAN_PROTECT = module_product.FAN_PROTECT
|
||||
|
||||
FANS_DEF = module_product.FANS_DEF
|
||||
MONITOR_SYS_LED = module_product.MONITOR_SYS_LED
|
||||
MONITOR_FANS_LED = module_product.MONITOR_FANS_LED
|
||||
MONITOR_SYS_FAN_LED = module_product.MONITOR_SYS_FAN_LED
|
||||
MONITOR_SYS_PSU_LED = module_product.MONITOR_SYS_PSU_LED
|
||||
MONITOR_FAN_STATUS = module_product.MONITOR_FAN_STATUS
|
||||
MONITOR_PSU_STATUS = module_product.MONITOR_PSU_STATUS
|
||||
MONITOR_DEV_STATUS = module_product.MONITOR_DEV_STATUS
|
||||
MONITOR_DEV_STATUS_DECODE = module_product.MONITOR_DEV_STATUS_DECODE
|
||||
DEV_MONITOR_PARAM = module_product.DEV_MONITOR_PARAM
|
||||
SLOT_MONITOR_PARAM = module_product.SLOT_MONITOR_PARAM
|
||||
|
||||
|
||||
DEV_LEDS = module_product.DEV_LEDS
|
||||
MEM_SLOTS = module_product.MEM_SLOTS
|
||||
|
||||
MAC_AVS_PARAM = module_product.MAC_AVS_PARAM
|
||||
MAC_DEFAULT_PARAM = module_product.MAC_DEFAULT_PARAM
|
||||
E2TYPE = module_product.E2TYPE
|
||||
FRULISTS = module_product.FRULISTS
|
||||
rg_eeprom = "%d-%04x/eeprom" % (E2_LOC["bus"], E2_LOC["devno"])
|
||||
factest_module = module_product.factest_module
|
||||
|
||||
LOCAL_LED_CONTROL = module_product.LOCAL_LED_CONTROL
|
||||
|
||||
PCIe_DEV_LIST = module_product.PCIe_DEV_LIST
|
||||
PCIe_SPEED_ITEM = module_product.PCIe_SPEED_ITEM
|
||||
i2ccheck_params = module_product.i2ccheck_params
|
||||
|
||||
|
||||
class MONITOR_CONST:
|
||||
TEMP_MIN = module_product.MONITOR_TEMP_MIN
|
||||
K = module_product.MONITOR_K
|
||||
MAC_IN = module_product.MONITOR_MAC_IN
|
||||
DEFAULT_SPEED = module_product.MONITOR_DEFAULT_SPEED
|
||||
MAX_SPEED = module_product.MONITOR_MAX_SPEED
|
||||
MIN_SPEED = module_product.MONITOR_MIN_SPEED
|
||||
MAC_ERROR_SPEED = module_product.MONITOR_MAC_ERROR_SPEED
|
||||
FAN_TOTAL_NUM = module_product.MONITOR_FAN_TOTAL_NUM
|
||||
MAC_UP_TEMP = module_product.MONITOR_MAC_UP_TEMP
|
||||
MAC_LOWER_TEMP = module_product.MONITOR_MAC_LOWER_TEMP
|
||||
MAC_MAX_TEMP = module_product.MONITOR_MAC_MAX_TEMP
|
||||
|
||||
MAC_WARNING_THRESHOLD = module_product.MONITOR_MAC_WARNING_THRESHOLD
|
||||
OUTTEMP_WARNING_THRESHOLD = module_product.MONITOR_OUTTEMP_WARNING_THRESHOLD
|
||||
BOARDTEMP_WARNING_THRESHOLD = module_product.MONITOR_BOARDTEMP_WARNING_THRESHOLD
|
||||
CPUTEMP_WARNING_THRESHOLD = module_product.MONITOR_CPUTEMP_WARNING_THRESHOLD
|
||||
INTEMP_WARNING_THRESHOLD = module_product.MONITOR_INTEMP_WARNING_THRESHOLD
|
||||
|
||||
MAC_CRITICAL_THRESHOLD = module_product.MONITOR_MAC_CRITICAL_THRESHOLD
|
||||
OUTTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_OUTTEMP_CRITICAL_THRESHOLD
|
||||
BOARDTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_BOARDTEMP_CRITICAL_THRESHOLD
|
||||
CPUTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_CPUTEMP_CRITICAL_THRESHOLD
|
||||
INTEMP_CRITICAL_THRESHOLD = module_product.MONITOR_INTEMP_CRITICAL_THRESHOLD
|
||||
CRITICAL_NUM = module_product.MONITOR_CRITICAL_NUM
|
||||
SHAKE_TIME = module_product.MONITOR_SHAKE_TIME
|
||||
MONITOR_INTERVAL = module_product.MONITOR_INTERVAL
|
||||
MONITOR_FALL_TEMP = module_product.MONITOR_FALL_TEMP
|
||||
|
||||
MONITOR_MAC_SOURCE_SYSFS = module_product.MONITOR_MAC_SOURCE_SYSFS
|
||||
MONITOR_MAC_SOURCE_PATH = module_product.MONITOR_MAC_SOURCE_PATH
|
||||
|
||||
|
||||
FANCTROLDEBUG = 0 # 1 means enable
|
||||
DEVMONITORDEBUG = 0 # 1 means enable
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
#docker exec -i pmon sensors "$@"
|
||||
|
||||
|
||||
#To probe sensors not part of lm-sensors
|
||||
if [ -r /usr/local/bin/platform_sensors.py ]; then
|
||||
python /usr/local/bin/platform_sensors.py
|
||||
fi
|
@ -1,15 +0,0 @@
|
||||
[Unit]
|
||||
Description= Ragile Global Initialize I2c drivers.
|
||||
After=local-fs.target
|
||||
Before=pmon.service ntp.service
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/device_i2c.py start
|
||||
ExecStop=/usr/local/bin/device_i2c.py stop
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
@ -1,12 +0,0 @@
|
||||
[Unit]
|
||||
Description= Fancontrol for Device.
|
||||
After=privatenetwork.service
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/fancontrol.py start
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
@ -1,24 +0,0 @@
|
||||
PWD = $(shell pwd)
|
||||
EXTRA_CFLAGS:= -I$(M)/include
|
||||
EXTRA_CFLAGS+= -Wall
|
||||
SUB_BUILD_DIR = $(PWD)/build
|
||||
SERVICE_DIR = $(PWD)/service
|
||||
INSTALL_DIR = $(SUB_BUILD_DIR)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR)
|
||||
INSTALL_SCRIPT_DIR = $(SUB_BUILD_DIR)/usr/local/bin
|
||||
INSTALL_LIB_DIR = $(SUB_BUILD_DIR)/usr/lib/python3.9/dist-packages
|
||||
INSTALL_SERVICE_DIR = $(SUB_BUILD_DIR)/lib/systemd/system
|
||||
INSTALL_ETC_DIR = $(SUB_BUILD_DIR)/etc
|
||||
UNSUPPORT_KERVER = 4.9.189
|
||||
|
||||
all:
|
||||
@if [ ! -d ${INSTALL_LIB_DIR} ]; then mkdir -p ${INSTALL_LIB_DIR} ;fi
|
||||
@if [ -d $(PWD)/lib/ ]; then cp -r $(PWD)/lib/* ${INSTALL_LIB_DIR} ;fi
|
||||
@if [ ! -d ${INSTALL_SCRIPT_DIR} ]; then mkdir -p ${INSTALL_SCRIPT_DIR} ;fi
|
||||
@if [ -d $(PWD)/script/ ]; then cp -r $(PWD)/script/* ${INSTALL_SCRIPT_DIR} ;fi
|
||||
@if [ ! -d ${INSTALL_ETC_DIR} ]; then mkdir -p ${INSTALL_ETC_DIR} ;fi
|
||||
@if [ -d $(INSTALL_SCRIPT_DIR) ]; then chmod +x $(INSTALL_SCRIPT_DIR)/* ;fi
|
||||
@if [ ! -d ${INSTALL_SERVICE_DIR} ]; then mkdir -p ${INSTALL_SERVICE_DIR} ;fi
|
||||
if [ -d $(SERVICE_DIR) ]; then cp -r $(SERVICE_DIR)/* $(INSTALL_SERVICE_DIR) ;fi
|
||||
clean:
|
||||
rm -rf $(SUB_BUILD_DIR)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,67 +0,0 @@
|
||||
[products]
|
||||
6 = BMCEEPROM
|
||||
17 = CPUM-C7EDN6-U2
|
||||
26 = EMMC-CARD
|
||||
33 = RA-B6010-48GT4X
|
||||
# 1 TLV EEPROM 0x56
|
||||
# 2 X86 CPU EEPROM
|
||||
# 3 BMC EEPROM
|
||||
# 4 CPU BASE_BOARD EEPROM 0x57
|
||||
# 5 MAC BOARD EEPROM
|
||||
# 6.Line card EEPROM (128)
|
||||
# 7.Fan adapter EEPROM
|
||||
# 8.Fan the small plate EEPROM
|
||||
# 9.PSU FRU EEPROM
|
||||
[typename]
|
||||
1= tlveeprom
|
||||
2= x86cpueeprom
|
||||
3= bmceeprom
|
||||
4= cpueeprom
|
||||
5= maceeprom
|
||||
6= sloteeprom
|
||||
7= fanconnecteeprom
|
||||
8= M1HFANI-F
|
||||
9= M1HFANI-R
|
||||
A= M2HFANI-F
|
||||
B= M2HFANI-R
|
||||
C= psu
|
||||
M = RA-EMMC-CARD
|
||||
Q = ibvbeeprom
|
||||
|
||||
[BMCEEPROM-3]
|
||||
boardinfoarea.ispresent = 1
|
||||
boardinfoarea.boardManufacturer = Ragile
|
||||
boardinfoarea.boradProductName = BMC
|
||||
boardinfoarea.boardSerialNumber = 0000000000000
|
||||
boardinfoarea.boardPartNumber = BMC
|
||||
boardinfoarea.FRUFileID = 6-3
|
||||
boardinfoarea.boardextra1 = AA
|
||||
|
||||
[RA-B6010-48GT4X-4]
|
||||
productInfoArea.ispresent = 1
|
||||
productInfoArea.productManufacturer = Ragile
|
||||
productInfoArea.productName = RA-B6010-48GT4X
|
||||
productInfoArea.productPartModelName = RA-B6010-48GT4X
|
||||
productInfoArea.productVersion = 00
|
||||
productInfoArea.productSerialNumber = 0000000000000
|
||||
productInfoArea.FRUFileID = 33-4
|
||||
productInfoArea.productExtra1 = 2020-12-20
|
||||
productInfoArea.productExtra2 = 1a2b3c4d5e6f
|
||||
productInfoArea.productExtra3 = 2
|
||||
|
||||
boardinfoarea.ispresent = 1
|
||||
boardinfoarea.boardManufacturer = Ragile
|
||||
boardinfoarea.boradProductName = RA-B6010-48GT4X
|
||||
boardinfoarea.boardSerialNumber = 0000000000000
|
||||
boardinfoarea.boardPartNumber = RA-B6010-48GT4X
|
||||
boardinfoarea.FRUFileID = 33-4
|
||||
boardinfoarea.boardextra1 = AA
|
||||
|
||||
[EMMC-CARD-M]
|
||||
boardinfoarea.ispresent = 1
|
||||
boardinfoarea.boardManufacturer = Ragile
|
||||
boardinfoarea.boradProductName = EMMC-CARD
|
||||
boardinfoarea.boardSerialNumber = 0000000000000
|
||||
boardinfoarea.boardPartNumber = RA-EMMC-CARD
|
||||
boardinfoarea.FRUFileID = 26-M
|
||||
boardinfoarea.boardextra1 = AA
|
@ -1,64 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
import os
|
||||
import syslog
|
||||
import logging
|
||||
import subprocess
|
||||
import shlex
|
||||
|
||||
SYSLOG_IDENTIFIER = "LOGUTIL"
|
||||
|
||||
# ========================== Syslog wrappers ==========================
|
||||
|
||||
def log_info(msg,log_type=SYSLOG_IDENTIFIER, also_print_to_console=False):
|
||||
syslog.openlog(log_type)
|
||||
syslog.syslog(syslog.LOG_INFO, msg)
|
||||
syslog.closelog()
|
||||
|
||||
if also_print_to_console:
|
||||
click.echo(msg)
|
||||
|
||||
|
||||
def log_debug(msg, log_type=SYSLOG_IDENTIFIER, also_print_to_console=False):
|
||||
try:
|
||||
syslog.openlog(log_type)
|
||||
syslog.syslog(syslog.LOG_DEBUG, msg)
|
||||
syslog.closelog()
|
||||
|
||||
if also_print_to_console:
|
||||
click.echo(msg)
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
|
||||
|
||||
def log_warning(msg, log_type=SYSLOG_IDENTIFIER, also_print_to_console=False):
|
||||
syslog.openlog(log_type)
|
||||
syslog.syslog(syslog.LOG_WARNING, msg)
|
||||
syslog.closelog()
|
||||
|
||||
if also_print_to_console:
|
||||
click.echo(msg)
|
||||
|
||||
def log_error(msg, log_type=SYSLOG_IDENTIFIER, also_print_to_console=False):
|
||||
syslog.openlog(log_type)
|
||||
syslog.syslog(syslog.LOG_ERR, msg)
|
||||
syslog.closelog()
|
||||
|
||||
if also_print_to_console:
|
||||
click.echo(msg)
|
||||
|
||||
restful_logger_path = "/var/log/bmc_restful.log"
|
||||
def bmc_restful_logger(message):
|
||||
if not os.path.isfile(restful_logger_path):
|
||||
cmd = "sudo touch %s && sudo chmod +x %s" % (
|
||||
restful_logger_path, restful_logger_path)
|
||||
subprocess.Popen(
|
||||
shlex.split(cmd), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
logging.basicConfig(filename=restful_logger_path,
|
||||
filemode='a',
|
||||
format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
|
||||
datefmt='%H:%M:%S',
|
||||
level=logging.INFO)
|
||||
|
||||
logging.info(message)
|
@ -1,304 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import shlex
|
||||
import datetime
|
||||
import os
|
||||
import ssl
|
||||
import subprocess
|
||||
import syslog
|
||||
|
||||
class Redfish_Api():
|
||||
BmcBaseUrl = 'http://240.1.1.1:8080'
|
||||
ThermalUrl = '/redfish/v1/Chassis/1/Thermal'
|
||||
PowerUrl = '/redfish/v1/Chassis/1/Power'
|
||||
ThresholdSensorsUrl = '/redfish/v1/Chassis/1/ThresholdSensors'
|
||||
FanSpeedUrl = '/redfish/v1/Chassis/1/Thermal/Actions/Oem/Ragile/Fan.SetSpeed'
|
||||
BoardsUrl = '/redfish/v1/Chassis/1/Boards/'
|
||||
BoardLedUrl = "/redfish/v1/Chassis/1/Boards/{}/Actions/Oem/Ragile/Boards.SetLED"
|
||||
|
||||
# Maximum time in seconds that you allow the connection to the server to take.
|
||||
connect_timeout = 30
|
||||
# Maximum time in seconds that you allow the whole operation to take
|
||||
operation_timeout = 300
|
||||
|
||||
default_prefix='/redfish/v1/'
|
||||
session = None
|
||||
__DEBUG__ = "N"
|
||||
__DUMP_RESP__ = "N"
|
||||
RST_STATUS = "status"
|
||||
RST_SUCCESS = "OK"
|
||||
refish_logger = None
|
||||
|
||||
def redfish_log_debug(self, msg):
|
||||
if (self.__DEBUG__ == "Y"):
|
||||
syslog.openlog("redfis_api")
|
||||
syslog.syslog(syslog.LOG_DEBUG, msg)
|
||||
syslog.closelog()
|
||||
|
||||
def redfish_log_error(self, msg):
|
||||
syslog.openlog("redfish_api")
|
||||
syslog.syslog(syslog.LOG_ERR, msg)
|
||||
syslog.closelog()
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def get_full_url(self, url):
|
||||
return self.BmcBaseUrl + url
|
||||
|
||||
def _exec_cmd(self, cmd):
|
||||
self.redfish_log_debug("Cmd: %s" % cmd)
|
||||
p = subprocess.Popen(shlex.split(cmd), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
p.wait()
|
||||
self.redfish_log_debug("Cmd return: %d" % p.returncode)
|
||||
str_stdout = p.stdout.read().decode('utf-8')
|
||||
str_stderr = p.stderr.read().decode('utf-8')
|
||||
self.redfish_log_debug("Cmd stdout: %s" % str_stdout)
|
||||
if p.returncode !=0:
|
||||
self.redfish_log_error("Cmd: %s, failed! error msg:%s" % (cmd, str_stderr))
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
ret = json.loads(str_stdout)
|
||||
return ret
|
||||
except Exception as e:
|
||||
self.redfish_log_error("Cmd: %s, failed! stdout msg:%s" % (cmd, str_stdout))
|
||||
return None
|
||||
|
||||
def _redfish_get(self, url):
|
||||
self.redfish_log_debug("Get info from %s." % url)
|
||||
result = None
|
||||
try:
|
||||
cmd_get="curl --connect-timeout %d -m %d -X GET %s" % (self.connect_timeout, self.operation_timeout, self.get_full_url(url))
|
||||
result = self._exec_cmd(cmd_get)
|
||||
return result
|
||||
except Exception as e:
|
||||
self.redfish_log_error("error_message: %s" % e)
|
||||
return None
|
||||
|
||||
def _redfish_post(self, url, playload):
|
||||
self.redfish_log_debug("post url: %s" % url)
|
||||
self.redfish_log_debug("Playload: %s" % playload)
|
||||
|
||||
playload_json = json.dumps(playload)
|
||||
result = False
|
||||
try:
|
||||
cmd_post="curl --connect-timeout %d -m %d -X POST %s -d \'%s\'" % (self.connect_timeout, self.operation_timeout, self.get_full_url(url), playload_json)
|
||||
ret_msg = self._exec_cmd(cmd_post)
|
||||
if ret_msg == None:
|
||||
return False
|
||||
elif ret_msg["success"] == False:
|
||||
redfish_log_error("Url: '%s', Playload: '%s', Bmc return failed, error_message: %s" % (url, playload_json, ret_msg["Message"]))
|
||||
result = False
|
||||
else:
|
||||
result = True
|
||||
return result
|
||||
except Exception as e:
|
||||
redfish_log_error("error_message: %s" % e)
|
||||
return False
|
||||
|
||||
def get_thermal(self):
|
||||
"""Get thermal info
|
||||
:returns: class 'redfish.rest.v1.RestResponse' or None when failed
|
||||
"""
|
||||
return self._redfish_get(self.ThermalUrl)
|
||||
|
||||
def get_power(self):
|
||||
"""Get power info
|
||||
:returns: class 'redfish.rest.v1.RestResponse' or None when failed
|
||||
"""
|
||||
return self._redfish_get(self.PowerUrl)
|
||||
|
||||
def get_thresholdSensors(self):
|
||||
"""Get thresholdSensors info
|
||||
:returns: class 'redfish.rest.v1.RestResponse' or None when failed
|
||||
"""
|
||||
return self._redfish_get(self.ThresholdSensorsUrl)
|
||||
|
||||
def post_odata(self, odata_id, playload):
|
||||
"""post odata info
|
||||
:params odata_id: the specified odata_id path
|
||||
:type odata_id: string
|
||||
:playload: info to post
|
||||
:type: dictionary
|
||||
:returns: True or False
|
||||
"""
|
||||
if odata_id is None or playload is None:
|
||||
print("post failed: odata_id or playload is None")
|
||||
return False
|
||||
return self._redfish_post(odata_id, playload)
|
||||
|
||||
def get_odata(self, odata_id):
|
||||
"""Get odata info
|
||||
:params odata_id: the specified odata_id path
|
||||
:type odata_id: string
|
||||
:returns: class 'redfish.rest.v1.RestResponse' or None when failed
|
||||
"""
|
||||
if odata_id is None:
|
||||
print("Get odata_id failed: odata_id is None")
|
||||
return None
|
||||
return self._redfish_get(odata_id)
|
||||
|
||||
def post_fanSpeed(self, playload):
|
||||
"""post odata info
|
||||
:playload: info to post
|
||||
:type: dictionary
|
||||
:returns: True or False
|
||||
"""
|
||||
if playload is None:
|
||||
print("post failed: playload is None")
|
||||
return False
|
||||
return self._redfish_post(self.FanSpeedUrl, playload)
|
||||
|
||||
def get_board(self, board_name="indicatorboard"):
|
||||
"""Get board info
|
||||
:board_name: name of board, default is "indicatorboard"
|
||||
:type: string
|
||||
:returns: class'redfish.rest.v1.RestResponse' or None when failed
|
||||
"""
|
||||
if board_name is None :
|
||||
print("get failed: board_name is None")
|
||||
return None
|
||||
return self._redfish_get(self.BoardsUrl + board_name)
|
||||
|
||||
def post_boardLed(self, playload, board_name="indicatorboard"):
|
||||
"""post boardLed info
|
||||
:board_name: name of board, default is "indicatorboard"
|
||||
:type: string
|
||||
:playload: info to post
|
||||
:type: dictionary
|
||||
:returns: True or False
|
||||
"""
|
||||
if board_name is None or playload is None:
|
||||
print("post failed: playload is None")
|
||||
return False
|
||||
return self._redfish_post(self.BoardLedUrl.format(board_name), playload)
|
||||
|
||||
''' not supported currently
|
||||
def post_thermal(self, playload):
|
||||
"""post thermal info
|
||||
:playload: info to post
|
||||
:type: dictionary
|
||||
:returns: True or False
|
||||
"""
|
||||
if playload is None:
|
||||
print("post_thermal failed: playload is None")
|
||||
return None
|
||||
return self._redfish_post(self.ThermalUrl, playload)
|
||||
|
||||
def post_power(self, playload):
|
||||
"""post power info
|
||||
:playload: info to post
|
||||
:type: dictionary
|
||||
:returns: True or False
|
||||
"""
|
||||
if playload is None:
|
||||
print("post_power failed: playload is None")
|
||||
return None
|
||||
return self._redfish_post(self.PowerUrl, playload)
|
||||
|
||||
def post_thresholdSensors(self, playload):
|
||||
"""post thresholdSensors info
|
||||
:playload: info to post
|
||||
:type: dictionary
|
||||
:returns: True or False
|
||||
"""
|
||||
if playload is None:
|
||||
print("post_thresholdSensors failed: playload is None")
|
||||
return None
|
||||
return self._redfish_post(self.ThresholdSensorsUrl, playload)
|
||||
|
||||
def get_fanSpeed(self):
|
||||
"""Get board led info
|
||||
:returns: class'redfish.rest.v1.RestResponse' or None when failed
|
||||
"""
|
||||
return self._redfish_get(self.FanSpeedUrl)
|
||||
|
||||
def post_board(self, playload, board_name="indicatorboard"):
|
||||
"""post board info
|
||||
:board_name: name of board, default is "indicatorboard"
|
||||
:type: string
|
||||
:playload: info to post
|
||||
:type: dictionary
|
||||
:returns: True or False
|
||||
"""
|
||||
if board_name is None or playload is None:
|
||||
print("post failed: playload is None")
|
||||
return False
|
||||
return self._redfish_post(self.BoardsUrl + board_name, playload)
|
||||
|
||||
def get_boardLed(self, board_name="indicatorboard"):
|
||||
"""Get boardLed info
|
||||
:board_name: name of board, default is "indicatorboard"
|
||||
:type: string
|
||||
:returns: class'redfish.rest.v1.RestResponse' or None when failed
|
||||
"""
|
||||
if board_name is None :
|
||||
print("get failed: board_name is None")
|
||||
return None
|
||||
return self._redfish_get(self.BoardsUrl % board_name)
|
||||
|
||||
'''
|
||||
|
||||
'''
|
||||
if __name__ == '__main__':
|
||||
redfish = Redfish_Api()
|
||||
|
||||
### get
|
||||
# boards
|
||||
ret = redfish.get_board()
|
||||
if ret is None:
|
||||
print("get failed: board")
|
||||
else:
|
||||
print("get succeeded, board:%s" % ret)
|
||||
|
||||
ret = redfish.get_thresholdSensors()
|
||||
if ret is None:
|
||||
print("get failed: threshold")
|
||||
else:
|
||||
print("get succeeded, threshold:%s" % ret)
|
||||
|
||||
ret = redfish.get_power()
|
||||
if ret is None:
|
||||
print("get failed: power")
|
||||
else:
|
||||
print("get succeeded, power:%s" % ret)
|
||||
|
||||
ret = redfish.get_thermal()
|
||||
if ret is None:
|
||||
print("get failed:thermal")
|
||||
else:
|
||||
print("get succeeded,thermal:%s" % ret)
|
||||
|
||||
# get playload
|
||||
resp = redfish.get_thresholdSensors()
|
||||
if (resp != None):
|
||||
print(resp["@odata.id"])
|
||||
print(resp["@odata.type"])
|
||||
print(resp["Id"])
|
||||
print(resp["Name"])
|
||||
else:
|
||||
print("Failed: get_thresholdSensors")
|
||||
|
||||
### post
|
||||
# fanSpeed
|
||||
playload = {}
|
||||
playload["FanName"] = 'Fan0'
|
||||
playload["FanSpeedLevelPercents"] = "70"
|
||||
print("post fanSpeed:%s" % redfish.post_fanSpeed(playload))
|
||||
|
||||
#{"LEDs": [{"IndicatorLEDColor": "green","LEDType": "sys"},{"IndicatorLEDColor": "off","LEDType": "pwr"},{"IndicatorLEDColor": "green","LEDType": "fan"}]}
|
||||
playload = {}
|
||||
led = {}
|
||||
led1 = {}
|
||||
led_list = []
|
||||
led["IndicatorLEDColor"] = "green"
|
||||
led["LEDType"] = "sys"
|
||||
led1["IndicatorLEDColor"] = "off"
|
||||
led1["LEDType"] = "pwr"
|
||||
led_list.append(led)
|
||||
led_list.append(led1)
|
||||
playload["LEDs"] = led_list
|
||||
# boardsLed
|
||||
print("post boardLed:%s" % redfish.post_boardLed(playload))
|
||||
'''
|
@ -1,290 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import mmap
|
||||
configfile_pre = "/usr/local/bin/"
|
||||
import sys
|
||||
sys.path.append(configfile_pre)
|
||||
from ragileconfig import *
|
||||
import subprocess
|
||||
import pexpect
|
||||
import shlex
|
||||
|
||||
SYSLOG_IDENTIFIER = "UTILTOOL"
|
||||
|
||||
def os_system(cmd):
|
||||
status, output = subprocess.getstatusoutput(cmd)
|
||||
return status, output
|
||||
|
||||
def get_machine_info():
|
||||
if not os.path.isfile('/host/machine.conf'):
|
||||
return None
|
||||
machine_vars = {}
|
||||
with open('/host/machine.conf') as machine_file:
|
||||
for line in machine_file:
|
||||
tokens = line.split('=')
|
||||
if len(tokens) < 2:
|
||||
continue
|
||||
machine_vars[tokens[0]] = tokens[1].strip()
|
||||
return machine_vars
|
||||
|
||||
def get_platform_info(machine_info):
|
||||
if machine_info != None:
|
||||
if machine_info.__contains__('onie_platform'):
|
||||
return machine_info['onie_platform']
|
||||
elif machine_info.__contains__('aboot_platform'):
|
||||
return machine_info['aboot_platform']
|
||||
return None
|
||||
|
||||
'''
|
||||
def cpld_version_restful(url):
|
||||
if url == "" or len(url) <=0:
|
||||
print("invalid url")
|
||||
return
|
||||
bmc = BMCMessage()
|
||||
value = bmc.getBmcValue(url)
|
||||
json_dicts=json.dumps(value,indent=4)
|
||||
return json_dicts
|
||||
'''
|
||||
|
||||
def lpc_cpld_rd(reg_addr):
|
||||
try:
|
||||
regaddr = 0
|
||||
if type(reg_addr) == int:
|
||||
regaddr = reg_addr
|
||||
else:
|
||||
regaddr = int(reg_addr, 16)
|
||||
devfile = "/dev/lpc_cpld"
|
||||
fd = os.open(devfile, os.O_RDWR|os.O_CREAT)
|
||||
os.lseek(fd, regaddr, os.SEEK_SET)
|
||||
str = os.read(fd, 1)
|
||||
os.close(fd)
|
||||
return "%02x" % ord(str)
|
||||
except ValueError:
|
||||
return None
|
||||
except Exception as e:
|
||||
print (e)
|
||||
return None
|
||||
|
||||
|
||||
def my_log(txt):
|
||||
if DEBUG == True:
|
||||
print ("[RAGILE]:",)
|
||||
print (txt)
|
||||
return
|
||||
|
||||
def log_os_system(cmd, show):
|
||||
my_log (' Run :'+ cmd)
|
||||
status, output = subprocess.getstatusoutput(cmd)
|
||||
my_log (" with result :" + str(status))
|
||||
my_log (" output :" + output)
|
||||
if status:
|
||||
log_error('Failed :%s msg:%s'%(cmd,output))
|
||||
if show:
|
||||
print ('Failed :'+ cmd)
|
||||
return status, output
|
||||
|
||||
def password_command(cmd, password, exec_timeout=30):
|
||||
|
||||
newkey = 'continue connecting'
|
||||
log_os_system("rm -rf ~/.ssh", 0)
|
||||
msg = ""
|
||||
try_times = 3
|
||||
try_times_conter = try_times
|
||||
while try_times_conter:
|
||||
child = pexpect.spawn(cmd)
|
||||
if try_times != try_times_conter:
|
||||
time.sleep(5)
|
||||
try_times_conter -= 1
|
||||
try:
|
||||
i = child.expect([pexpect.TIMEOUT, newkey, 'password: ',"refused",pexpect.EOF],timeout=30)
|
||||
# If the login times out, print an error message and exit.
|
||||
if i == 0: # Timeout
|
||||
msg = 'connect to BMC timeout'
|
||||
continue
|
||||
# no public key
|
||||
if i == 1:
|
||||
child.sendline ('yes')
|
||||
i = child.expect([pexpect.TIMEOUT, 'password: '],timeout=30)
|
||||
if i == 0: # Timeout
|
||||
msg = 'connect to BMC timeout'
|
||||
continue
|
||||
if i == 1:# Go below and enter the logic of the password
|
||||
i = 2
|
||||
if i == 2: # Enter the password
|
||||
child.sendline (password)
|
||||
i = child.expect([pexpect.EOF, pexpect.TIMEOUT], exec_timeout)
|
||||
if i == 0:
|
||||
return True,child.before
|
||||
if i == 1:
|
||||
msg = str(child.before)+"\nBMC run commands timeout"
|
||||
return False,msg
|
||||
if i == 3: # BMC Connection refused
|
||||
msg = 'connect to BMC failed'
|
||||
continue
|
||||
if i == 4:
|
||||
msg = child.before
|
||||
except Exception as e:
|
||||
msg = str(child.before)+"\nconnect to BMC failed"
|
||||
|
||||
return False,msg
|
||||
|
||||
def password_command_realtime(ssh_header, ssh_cmd, password,key_words, exec_timeout=30):
|
||||
|
||||
key_word_end = key_words.get("key_word_end")
|
||||
key_word_pass = key_words.get("key_word_pass")
|
||||
key_word_noshow = key_words.get("key_word_noshow")
|
||||
# Prevents waiting caused by BMC restart
|
||||
key_word_exit = key_words.get("key_word_exit")
|
||||
|
||||
if None in [key_word_end,key_word_pass]:
|
||||
print ("Missing parameters")
|
||||
return False
|
||||
|
||||
newkey = 'continue connecting'
|
||||
log_os_system("rm -rf ~/.ssh", 0)
|
||||
msg = ""
|
||||
try_times = 3
|
||||
key_word_pass_flag = False
|
||||
try_times_conter = try_times
|
||||
child = pexpect.spawn(ssh_header)
|
||||
try:
|
||||
i = child.expect([pexpect.TIMEOUT,newkey, 'password: ',"refused",pexpect.EOF],timeout=30)
|
||||
# If the login times out, print an error message and exit.
|
||||
if i == 0: # Timeout
|
||||
msg = 'connect to BMC timeout'
|
||||
# no public key
|
||||
if i == 1:
|
||||
child.sendline ('yes')
|
||||
i = child.expect([pexpect.TIMEOUT, 'password: '],timeout=30)
|
||||
if i == 0: # Timeout
|
||||
msg = 'connect to BMC timeout'
|
||||
if i == 1:# Go below and enter the logic of the password
|
||||
i = 2
|
||||
|
||||
if i == 2: # Enter the password
|
||||
child.sendline (password)
|
||||
i = child.expect([pexpect.EOF, "\r",pexpect.TIMEOUT], exec_timeout)
|
||||
if i == 0:
|
||||
print (child.before)
|
||||
return key_word_pass_flag
|
||||
if i == 1:
|
||||
child.sendline(ssh_cmd)
|
||||
# amount received is similar to root@switch2 in order to avoid misjudgment about the end of execution
|
||||
usr_symble_first = True
|
||||
bmc_str_tmp=""
|
||||
while True:
|
||||
i = child.expect([pexpect.EOF,"\r","\n",key_word_end, pexpect.TIMEOUT], exec_timeout)
|
||||
if i == 0:
|
||||
return key_word_pass_flag
|
||||
elif i in [1,2]:
|
||||
if key_word_noshow == None or key_word_noshow not in child.before:
|
||||
bmc_str, times = re.subn("\r|\n","",child.before)
|
||||
if len(bmc_str) > 1:
|
||||
print (bmc_str)
|
||||
bmc_str_tmp=bmc_str_tmp + bmc_str
|
||||
# print bmc_str_tmp
|
||||
# if key_word_pass in child.before:
|
||||
if re.search(key_word_pass,bmc_str_tmp) != None:
|
||||
key_word_pass_flag = True
|
||||
if key_word_exit != None and key_word_exit in child.before:
|
||||
# Give the BMC time to execute the last command
|
||||
time.sleep(3)
|
||||
return key_word_pass_flag
|
||||
elif i == 3 :
|
||||
if usr_symble_first:
|
||||
usr_symble_first = False
|
||||
else:
|
||||
return key_word_pass_flag
|
||||
|
||||
if i == 3: # BMC Connection refused
|
||||
msg = 'connect to BMC failed'
|
||||
if i == 4:
|
||||
msg = child.before
|
||||
except Exception as e:
|
||||
print (e)
|
||||
msg = str(child.before)+"\nconnect to BMC error"
|
||||
print (msg)
|
||||
|
||||
return False
|
||||
|
||||
def get_sys_execute2(cmd, key_word_pass):
|
||||
# key_word_pass_flag1 = False
|
||||
key_word_pass_flag = False
|
||||
filename = "/tmp/diag_excute_out"
|
||||
cmd = cmd + "|tee %s" % filename
|
||||
p = subprocess.Popen(shlex.split(cmd), shell=False)
|
||||
p.wait()
|
||||
with open(filename, 'r') as f:
|
||||
str1 = f.read()
|
||||
if key_word_pass in str1:
|
||||
key_word_pass_flag = True
|
||||
# if key_word_pass_flag1 and "100%" in str1:
|
||||
# key_word_pass_flag = True
|
||||
log_os_system("rm %s"%filename,0)
|
||||
return key_word_pass_flag
|
||||
|
||||
|
||||
BMC_PATH = "PATH=/usr/sbin/:/bin/:/usr/bin/:/sbin"
|
||||
RETURN_KEY1 = "code"
|
||||
RETURN_KEY2 = "msg"
|
||||
DEBUG = False
|
||||
|
||||
def rgi2cget(bus, devno, address):
|
||||
command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address)
|
||||
retrytime = 6
|
||||
ret_t = ""
|
||||
for i in range(retrytime):
|
||||
ret, ret_t = os_system(command_line)
|
||||
if ret == 0:
|
||||
return True, ret_t
|
||||
time.sleep(0.1)
|
||||
return False, ret_t
|
||||
|
||||
def strtoint(str): # Hexadecimal string to int,"4040"/"0x4040"/"0X4040" = 16448
|
||||
value = 0
|
||||
rest_v = str.replace("0X", "").replace("0x", "")
|
||||
for index in range(len(rest_v)):
|
||||
value |= int(rest_v[index], 16) << ((len(rest_v) - index - 1) * 4)
|
||||
return value
|
||||
|
||||
def pci_read(pcibus, slot, fn , bar, offset):
|
||||
if offset % 4 != 0:
|
||||
return None
|
||||
filename = "/sys/bus/pci/devices/0000:%02x:%02x.%x/resource%d" % (int(pcibus), int(slot), int(fn), int(bar))
|
||||
file = open(filename, "r+")
|
||||
size = os.path.getsize(filename)
|
||||
data = mmap.mmap(file.fileno(), size)
|
||||
result = data[offset: offset + 4]
|
||||
s = result[::-1]
|
||||
val = 0
|
||||
for i in range(0, len(s)):
|
||||
val = val << 8 | ord(s[i])
|
||||
data.close()
|
||||
file.close()
|
||||
return val
|
||||
|
||||
###########################################
|
||||
# Run the DMI command to obtain the BIOS information
|
||||
###########################################
|
||||
def getDmiSysByType(type_t):
|
||||
ret, log = os_system("which dmidecode ")
|
||||
if ret != 0 or len(log) <= 0:
|
||||
error = "cmd find dmidecode"
|
||||
return False, error
|
||||
cmd = log + " -t %s" % type_t
|
||||
# Get the total first
|
||||
ret1, log1 = os_system(cmd)
|
||||
if ret != 0 or len(log1) <= 0:
|
||||
return False, "Command error[%s]" % cmd
|
||||
its = log1.replace("\t", "").strip().split("\n")
|
||||
ret = {}
|
||||
for it in its:
|
||||
if ":" in it:
|
||||
key = it.split(":")[0].lstrip()
|
||||
value = it.split(":")[1].lstrip()
|
||||
ret[key] = value
|
||||
return True, ret
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user