📄 8253xplx.c
字号:
/* -*- linux-c -*- *//* plx9050.c * Copyright (C) 2000 by Francois Wautier * based on code from Bjorn Davis * * Read and write command for the eprom attached to * the PLX9050 *//* Modifications and extensions * Copyright (C) 2001 By Joachim Martillo, Telford Tools, 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. **//* We handle PCI devices */#include <linux/pci.h> /* We need to use ioremap */ #include <asm/io.h>#include <linux/delay.h> /* Joachim Martillo modified this file */ /* so that it had no dependencies on specific */ /* Aurora adapter card or ESSC* structures*/ /* The original file use TRUE for 1 and */ /* FALSE for 0. This convention conflicted */ /* with other conventions throughout LINUX */ /* also TRUE was used for setting an eprom */ /* bit which is a slight semantic confusion. */ /* I just used 0 and 1 */#include "Reg9050.h"/* * Write a single bit to the serial EPROM interface. */ /* eprom_ctl is the */ /* address of the 9050 */ /* eprom control register */ /* The original & operation */ /* looks wrong. I am surprised */ /* the code worked */ /* but I left the parentheses */ /* because readl, writel etc */ /* are macros*/ /* The following function */ /* assumes the proper bit */ /* in the serial eprom */ /* has already been selected*/ /* The 9050 registers are 32 bits */ /* hence the readl and writel */ /* macros are invoked*/ /* eprom_ctl must be a virtual */ /* address*/static void plx9050_eprom_wbit(unsigned int* eprom_ctl, unsigned int val){ unsigned int ctrl; /* get the initial value of the CTRL register */ ctrl = readl((eprom_ctl)); /* set or clear the data bit */ if (val) { ctrl |= PLX_CTRL_SEPWD; } else { ctrl &= ~PLX_CTRL_SEPWD; } writel(ctrl, (eprom_ctl)); udelay(1); /* Toggle the clock line */ /* gets to the next bit */ /* in the serial eprom */ ctrl |= PLX_CTRL_SEPCLK; writel(ctrl, (eprom_ctl)); udelay(1); /* Toggle the clock line */ ctrl &= ~PLX_CTRL_SEPCLK; writel(ctrl, (eprom_ctl)); udelay(1);}/* * Run a serial EPROM command. Returns 1 on success, * 0 otherwise. *//* This routine does the write of data but only sets up *//* for a read*//* the write goes from most significant to least significant */unsigned int plx9050_eprom_cmd(unsigned int* eprom_ctl, unsigned char cmd, unsigned char addr, unsigned short data){ unsigned int ctrl; unsigned char shiftb; unsigned short shiftw; unsigned int l, v; unsigned char ret; int i; ret = 1; shiftb = addr << (NM93_BITS_PER_BYTE - NM93_ADDRBITS); /* looks a bizarre way to mask out unused bits */ ctrl = readl((eprom_ctl)); ctrl &= ~(PLX_CTRL_SEPCLK | PLX_CTRL_SEPWD); writel(ctrl, (eprom_ctl)); udelay(1); ctrl |= PLX_CTRL_SEPCS; writel(ctrl, (eprom_ctl)); plx9050_eprom_wbit(eprom_ctl, 1); /* * Clock out the command */ plx9050_eprom_wbit(eprom_ctl, (cmd & 0x02) != 0); plx9050_eprom_wbit(eprom_ctl, (cmd & 0x01) != 0); /* * Clock out the address */ i = NM93_ADDRBITS; while (i != 0) /* here we get to the correct */ /* short in the serial eprom*/ { /* printf("Loop #1\n"); */ plx9050_eprom_wbit(eprom_ctl, (shiftb & 0x80) != 0); shiftb <<= 1; i--; } if (cmd == NM93_WRITECMD) /* now do the write if */ /* a write is to be done*/ { /* write data? */ /* * Clock out the data */ shiftw = data; i = NM93_BITS_PER_WORD; while (i != 0) { /* printf("Loop #2\n"); */ plx9050_eprom_wbit(eprom_ctl, (shiftw & 0x8000) != 0); shiftw <<= 1; i--; } /* * De-assert chip select for a short period of time */ ctrl = readl((eprom_ctl)); ctrl &= ~PLX_CTRL_SEPCS; writel(ctrl, (eprom_ctl)); udelay(2); /* * Re-assert chip select */ ctrl |= PLX_CTRL_SEPCS; writel(ctrl, (eprom_ctl)); /* * Wait for a low to high transition of DO */ i = 20000; ctrl = readl((eprom_ctl)); l = (ctrl & PLX_CTRL_SEPRD); while (i != 0) { /* printf("Loop #3\n"); */ ctrl = readl((eprom_ctl)); v = (ctrl & PLX_CTRL_SEPRD); if (v != 0 && l == 0) { break; } l = v; udelay(1); i--; } if (i == 0) { printk("plx9050: eprom didn't go low to high"); ret = 0; } } if (cmd != NM93_READCMD) /* not a read -- terminate */ { /* * De-assert the chip select. */ ctrl = readl((eprom_ctl)); ctrl &= ~PLX_CTRL_SEPCS; writel(ctrl,(eprom_ctl)); } /* otherwise left in read state */ return ret;}/* * Read the serial EPROM. Returns 1 on success, 0 on failure. * reads in shorts (i.e., 16 bits at a time.) * */unsigned intplx9050_eprom_read(unsigned int* eprom_ctl, unsigned short *ptr, unsigned char addr, unsigned short len){ unsigned short shiftw; int i; unsigned int ctrl; if (!plx9050_eprom_cmd(eprom_ctl, NM93_READCMD, addr, (unsigned short) 0x0)) /* set up read */ { return 0; } ctrl = readl((eprom_ctl)); /* synchronize */ while (len-- > 0) /* now read one word at a time */ { shiftw = 0; ctrl &= ~PLX_CTRL_SEPCLK; writel(ctrl, (eprom_ctl)); udelay(1); i = NM93_BITS_PER_WORD; while (1) /* now read one bit at a time, */ /* left shifting each bit */ { ctrl |= PLX_CTRL_SEPCLK; writel(ctrl, (eprom_ctl)); udelay(1); ctrl = readl((eprom_ctl)); if ((ctrl & PLX_CTRL_SEPRD) != 0) { shiftw |= 0x1; } i--; if (i == 0) { break; } shiftw <<= 1; ctrl &= ~PLX_CTRL_SEPCLK; writel(ctrl, (eprom_ctl)); udelay(1); } *ptr++ = shiftw; } ctrl &= ~PLX_CTRL_SEPCS; writel(ctrl, (eprom_ctl)); udelay(1); ctrl &= ~PLX_CTRL_SEPCLK; writel(ctrl, (eprom_ctl)); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -